HOOK-API
1. 基础 Hook
1. useState
// 返回一个 state,以及更新 state 的函数。 const [state, setState] = useState(initialState);
- 惰性初始 state
/* 如果初始 state 需要通过复杂计算获得,则可以传入一个函数, 在函数中计算并返回初始的 state,此函数只在初始渲染时被调用:*/ const [state, setState] = useState(() => { const initialState = someExpensiveComputation(props); return initialState; });
2. useEffect
// 接收一个包含命令式、且可能有副作用代码的函数。 // 如: 改变 DOM、添加订阅、设置定时器、记录日志以及执行其他包含副作用的操作 // 虽然 useEffect 会在浏览器绘制后延迟执行,但会保证在任何新的渲染前执行 // 用户可见的 DOM 变更,可使用 useLayoutEffect useEffect(didUpdate); // 代码示例 useEffect( () => { // 这里写 componentDidMount、componentDidUpdate 的操作 const subscription = props.source.subscribe(); return () => { // 此处类似 componentWillUnMonut subscription.unsubscribe(); }; }, // 这里是限制当 props.source改变时,才执行方法体的方法 [props.source], );
3. useContext
// 接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。 /* useContext(MyContext) 只是让你能够读取 context 的值以及订阅 context 的变化。 你仍然需要在上层组件树中使用 <MyContext.Provider> 来为下层组件提供 context。*/ const value = useContext(MyContext);
2. 额外的 Hook
1. useReducer
/* 它接收一个形如 (state, action) => newState 的 reducer, 并返回当前的 state 以及与其配套的 dispatch 方法。*/ const [state, dispatch] = useReducer(reducer, initialArg, init);
- 惰性初始化
// 将 init 函数作为 useReducer 的第三个参数传入,这样初始 state 将被设置为 init(initialArg)。 function init(initialCount) { return {count: initialCount}; } function reducer(state, action) { switch (action.type) { case 'increment': return {count: state.count + 1}; case 'decrement': return {count: state.count - 1}; case 'reset': return init(action.payload); default: throw new Error(); } } function Counter({initialCount}) { const [state, dispatch] = useReducer(reducer, initialCount, init); return ( ); }
2. useCallback
3. useMemo
// 把“创建”函数和依赖项数组作为参数传入 useMemo,它仅会在某个依赖项改变时才重新计算 memoized 值。 // 这种优化有助于避免在每次渲染时都进行高开销的计算。 // (先编写在没有 useMemo 的情况下也可以执行的代码 —— 之后再在你的代码中添加 useMemo,以达到优化性能的目的。) const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
4. useRef
/* useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。 返回的 ref 对象在组件的整个生命周期内保持不变。*/ const refContainer = useRef(initialValue);
5. useImperativeHandle
/* useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值。 在大多数情况下,应当避免使用 ref 这样的命令式代码。 useImperativeHandle 应当与 forwardRef 一起使用:*/ useImperativeHandle(ref, createHandle, [deps])
- 一个例子
function FancyInput(props, ref) { const inputRef = useRef(); useImperativeHandle(ref, () => ({ focus: () => { inputRef.current.focus(); } })); return <input ref={inputRef} ... />; } FancyInput = forwardRef(FancyInput);
6. useLayoutEffect
-
- 可以使用它来读取 DOM 布局并同步触发重渲染。
- 尽可能使用标准的
useEffect
以避免阻塞视觉更新。
7. useDebugValue
// useDebugValue 可用于在 React 开发者工具中显示自定义 hook 的标签。 useDebugValue(value)