第六章 React Hooks
内容前瞻
本章将深入探讨 React Hooks 的核心概念与使用场景,涵盖 useState、useEffect、useRef、useMemo、useCallback 和 useContext 等常用 Hooks
- Hooks 的基本原理与使用方式
- 如何通过 Hooks 实现状态管理、生命周期控制、性能优化与组件通信
- Hooks 的实际应用场景与注意事项
Hooks 组件
Hooks 组件的本质
- 函数组件:Hooks 组件本质上是函数组件,基于函数作用域实现动态更新
- 动态与静态的折中:Hooks 组件结合了函数组件的简洁性与类组件的动态更新能力
- 更新机制
- 每次更新时,重新执行函数,创建新的函数作用域与闭包
- 通过 Hooks 管理状态与副作用,避免直接操作 DOM
useState
1. 基本使用
- 初始化
- 不需要变化的初始值,直接传递
- 需要加工的初始值,通过函数传递
- 特点
- 不支持部分状态修改,需通过扩展运算符实现
- React 18 中,
useState更新为异步批处理,减少渲染次数
示例:
jsx
const [num, setNum] = useState(1);
for (let i = 0; i < 10; i++) {
flushSync(() => {
setNum(num + 1); // 结果:11
});
}2. 性能优化
- 浅比较:
useState通过Object.is比较状态值,避免不必要的渲染 - 返回值:返回数组,
index[0]为状态值,index[1]为更新函数
useEffect
1. 基本使用
- 无依赖:
useEffect(callback),类似于componentDidMount,每次渲染后执行 - 空依赖:
useEffect(callback, []),仅在初次渲染后执行 - 有依赖:
useEffect(callback, [param]),初次渲染与依赖更新时执行 - 清理函数:
useEffect(() => { return () => {} }),组件卸载时执行
2. 执行顺序
- 优先执行清理函数:组件更新时,先执行上一次的清理函数,再执行新的
callback - 链表机制:通过
mountEffect和updateEffect管理副作用链表
3. 注意事项
- 异步处理:
useEffect不支持直接使用async函数,需手动封装 useLayoutEffect:在 DOM 更新前同步执行,避免闪烁问题
useRef
1. 基本功能
- 获取 DOM 引用:通过
ref获取真实 DOM 或子组件实例 - 转发 Ref:使用
React.forwardRef实现子组件 Ref 转发
示例:
jsx
const Child = React.forwardRef((props, ref) => {
return <div ref={ref}>Child Component</div>;
});2. useImperativeHandle
- 暴露子组件方法:通过
useImperativeHandle将子组件的状态与方法暴露给父组件
示例:
jsx
useImperativeHandle(ref, () => ({
stateA,
methodA,
}));useMemo 与 useCallback
1. useMemo
- 缓存计算结果:适用于消耗性能的计算操作,减少不必要的重复计算
- 使用场景:字符串、数字等原始值的缓存
示例:
jsx
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);2. useCallback
- 缓存函数引用:适用于父子组件通信,避免子组件不必要的更新
- 使用场景:函数、对象等引用值的缓存
示例:
jsx
const memoizedCallback = useCallback(() => {
doSomething(a, b);
}, [a, b]);useContext
1. 组件通信
- 单向数据流:父组件通过
props向子组件传递数据,子组件通过回调函数更新父组件状态 - 多层通信:使用
useContext实现祖先与后代组件的数据传递
2. 使用方式
- 创建上下文:jsx
const MyContext = React.createContext(); - 提供数据:jsx
<MyContext.Provider value={/* 数据 */}> <ChildComponent /> </MyContext.Provider> - 消费数据:jsx
const value = useContext(MyContext);
重难点 & 容易忽视的点
1. useEffect 的依赖项
- 空依赖:仅在组件挂载与卸载时执行
- 动态依赖:依赖项变化时触发
callback
2. useRef 的性能优势
- 引用不变:
useRef在组件更新前后引用相同,性能优于createRef
3. useMemo 与 useCallback 的区别
useMemo:缓存计算结果,适用于原始值useCallback:缓存函数引用,适用于引用值
总结
- Hooks 组件:基于函数作用域实现动态更新,结合了函数组件与类组件的优点
useState:管理组件状态,支持异步批处理与性能优化useEffect:控制副作用,支持清理函数与依赖项管理useRef:获取 DOM 引用,支持 Ref 转发与子组件方法暴露useMemo与useCallback:缓存计算结果与函数引用,优化性能useContext:实现组件通信,支持单向数据流与多层数据传递