const [state, setSate] = useState(initialState)
特征:
setState 标识稳定,组件重新渲染时不会变化,useState 返回的第一个值始终是最新的state
state 如果是对象,当只更新对象部分属性时,state更新不会合并对象
如果 state 不发生变化,调用 setState 将跳过更新
建议:将同一时间段更新的 state, 组合初始化在一起
函数式初始化 state
const [state, setState] = useState(()=>{ const initialState = someExpensiveComputation(props) return initialState })
更新 state 对象
setState((preState)=>{ return {...prevState, ...updatedValues}; })
useEffect 组件渲染之后异步执行回调,并在下次渲染前执行
useEffect(callback)//组件每次渲染,都会重新生成 useEffect useEffect(callback,[依赖参数])//组件每次渲染之后,根据依赖参数判断是否重新生成 useEffect useEffect(callback,[]) // 只在组件挂载时运行一次
useEffect Hook 对应的生命周期:
componentDidMount
componentDidUpdate
componentWillUnmount
依赖项频繁变化措施(引用官方例子):
function Counter() { const [count, setCount] = useState(0); useEffect(() => { const id = setInterval(() => { setCount(c => c + 1); // ? setCount 函数式变更,没有依赖项 }, 1000); return () => clearInterval(id); }, []); // ? return <h1>{count}</h1>; }
应用场景:
管理内部 state
结合 context,利用 dispatch 避免父组件向下传递回调
const TodosDispatch = React.createContext(null); // 父组件 function TodosApp() { // 提示:`dispatch` 不会在重新渲染之间变化 const [todos, dispatch] = useReducer(todosReducer); return ( <TodosDispatch.Provider value={dispatch}> <DeepTree/> </TodosDispatch.Provider> ); } // 子组件 function DeepTree(props) { // 获取 dispatch。 const dispatch = useContext(TodosDispatch); function handleClick() { dispatch({ type: ‘add‘, text: ‘hello‘ }); } return ( <button onClick={handleClick}>Add todo</button> ); }
函数式初始化(引用官方例子)
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);// 重新初始化 state,没用用到上一个state default: throw new Error(); } } function Counter({initialCount}) { const [state, dispatch] = useReducer(reducer, initialCount, init); return ( <> Count: {state.count} <button onClick={() => dispatch({type: ‘reset‘, payload: initialCount})}> // 传入参数 Reset </button> <button onClick={() => dispatch({type: ‘decrement‘})}>-</button> <button onClick={() => dispatch({type: ‘increment‘})}>+</button> </> ); }
用于性能优化
const memoizedCallback = useCallback( () => { doSomething(a, b); }, [a, b], );
用于性能优化,传入的函数在组件渲染时执行
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
const refContainer = useRef(initialValue); // refContainer 为 ref 对象 // refContainer.current 可以保存任何可变值
特征
useRef 每次渲染时返回同一个 ref 对象
变更 .current
属性不会引发组件重新渲染
如何检测 DOM 元素的变化?(官方例子)
function MeasureExample() { const [height, setHeight] = useState(0); const measuredRef = useCallback(node => { if (node !== null) { setHeight(node.getBoundingClientRect().height); } }, []);// 检测 ref 的回调函数 return ( <> <h1 ref={measuredRef}>Hello, world</h1> <h2>The above header is {Math.round(height)}px tall</h2> </> ); }
规则:函数必须以“use.."开头定义,内部可以调用其他Hook
应用场景:用于抽离共享逻辑和封装复杂的Hook
特征:
不同组件共用自定义Hook,不会共享state
组件可以多次调用自定义Hook
Hook之间可以传递信息(组件内的state传入自定义Hook,自定义Hook会随state变化而更新)
原文:https://www.cnblogs.com/seny-33/p/12219491.html