函数组件
//推荐使用✅ better
const WrapComponent: React.FC<ExtendedProps> = (props) => {
// return ...
};
//直接使用
export default WrapComponent;
// 或者
export default function (props: React.PropsWithChildren<SpinProps>) {
// return ...
}
const Notice: React.FC = () => {}
port * as React from 'react'
type changeFn = (e: React.FormEvent<HTMLInputElement>) => void
const App: React.FC = () => {
const [state, setState] = React.useState('')
const onChange: changeFn = e => {
setState(e.currentTarget.value)
}
✅ better
const onSubmit = (e: React.SyntheticEvent) => {
e.preventDefault()
const target = e.target as typeof e.target & {
password: { value: string }
} // 类型扩展
const password = target.password.value
}
return (
<form onSubmit={onSubmit}>
<input type="text" value={state} onChange={onChange} />
</form>
)
}
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。
调用
useState()Hook 来启用函数组件中的状态。useState(initialValue)的第一个参数initialValue是状态的初始值。[state, setState] = useState(initialValue)返回一个包含2个元素的数组:状态值和状态更新函数。使用新值调用状态更新器函数
setState(newState)更新状态。或者,可以使用一个回调setState(prev => next)来调用状态更新器,该回调将返回基于先前状态的新状态。调用状态更新器后,React 确保重新渲染组件,以使新状态变为当前状态。
demo:按按钮新增灯泡或者开关灯
import React, { useState } from 'react'; function Bulbs() { const [on, setOn] = useState(false); const [count, setCount] = useState(1); const lightSwitch = () => setOn(on => !on); const addBulbs = () => setCount(count => count + 1); const bulb = <div className={on ? 'bulb-on' : 'bulb-off'} />; const bulbs = Array(count).fill(bulb); return ( <> <div className="bulbs">{bulbs}</div> <button onClick={lightSwitch}>开/关</button> <button onClick={addBulbs}>添加灯泡</button> </> ); }
//给定初始化值情况下可以直接使用
import { useState } from 'react';
// ...
const [val, toggle] = useState(false);
// val 被推断为 boolean 类型
// toggle 只能处理 boolean 类型
//没有初始值(undefined)或初始 null
type AppProps = { message: string };
const App = () => {
const [data] = useState<AppProps | null>(null);✅ better
// const [data] = useState<AppProps | undefined>();
return <div>{data?.message}</div>;
};
你之前可能已经在 React 组件中执行过数据获取、订阅或者手动修改过 DOM。我们统一把这些操作称为“副作用”,或者简称为“作用”。
useEffect 就是一个 Effect Hook,给函数组件增加了操作副作用的能力。它跟 class 组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的用途,只不过被合并成了一个 API。(我们会在使用 Effect Hook 里展示对比 useEffect 和这些方法的例子。)
可以把 useEffect Hook 看做 componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合。
只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。
只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用。
下面这个组件在 React 更新 DOM 后会设置一个页面标题:
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// 相当于 componentDidMount 和 componentDidUpdate:
useEffect(() => {
// 使用浏览器的 API 更新页面标题
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
当你调用 useEffect 时,就是在告诉 React 在完成对 DOM 的更改后运行你的“副作用”函数。由于副作用函数是在组件内声明的,所以它们可以访问到组件的 props 和 state。默认情况下,React 会在每次渲染后调用副作用函数 —— 包括第一次渲染的时候。
