以 useEffect 与 React 组件的性能优化
2023-11-06 21:25:11
React 中 useEffect 使用问题
前言
最近看了一下 ant-design 中的 tree 组件源码时发现 useEffect 中根据 props 来计算当前函数组件的 state 的,感到好奇,因为这样会导致应用重新绘制一次,这样才导致组件 rerender,我看了源码后知道,这个 tree 组件的目的是为了复用一些子组件,减少重复渲染,但是这个操作就会导致组件重新渲染一次,性能会有损耗。
怎么解决这个问题呢?
第一种方法是使用 useMemo 将计算结果缓存起来,但是这种方式只适用于计算量较大的场景,如果计算量较小,使用这种方式反而会带来性能损耗。
第二种方法是使用 useRef 来存储计算结果,这种方式可以避免重新计算,但是需要手动管理计算结果的更新,相对来说比较麻烦。
第三种方法是使用 useReducer 来管理状态,这种方式可以避免重新计算,而且可以轻松地管理状态的更新,但是使用起来会比较复杂。
第四种方法是使用 useMutationEffect 来管理状态,这种方式可以避免重新计算,而且使用起来相对简单,但是它只适用于某些特定的场景。
在实际开发中,我们可以根据具体场景选择合适的方法来优化组件性能。
useEffect 的工作原理
useEffect 是 React 中的一个函数,用于在函数组件中管理状态和事件监听。它接受两个参数:一个回调函数和一个依赖项数组。回调函数会在组件第一次渲染后、每次更新后以及组件卸载前执行。依赖项数组用于控制组件的重新绘制。如果依赖项数组中的任何一项发生变化,组件就会重新绘制。
useEffect 的用法
在函数组件中使用 useEffect 来管理状态和事件监听,有以下几种方式:
- 使用 useEffect 来初始化状态
const MyComponent = () => {
const [count, setCount] = useState(0);
useEffect(() => {
// 初始化状态
setCount(10);
}, []);
};
- 使用 useEffect 来监听事件
const MyComponent = () => {
const [count, setCount] = useState(0);
useEffect(() => {
// 监听事件
window.addEventListener("click", () => {
setCount(count + 1);
});
// 清理事件监听器
return () => {
window.removeEventListener("click", () => {
setCount(count + 1);
});
};
}, []);
};
- 使用 useEffect 来控制组件的重新绘制
const MyComponent = ({ prop1, prop2 }) => {
const [count, setCount] = useState(0);
useEffect(() => {
// 控制组件的重新绘制
if (prop1 !== prevProp1 || prop2 !== prevProp2) {
setCount(count + 1);
}
}, [prop1, prop2]);
};
useEffect 的注意事项
在使用 useEffect 时,需要注意以下几点:
- useEffect 的回调函数会在组件第一次渲染后、每次更新后以及组件卸载前执行。因此,在回调函数中不要执行一些开销较大的操作,例如网络请求或复杂的计算。
- useEffect 的依赖项数组用于控制组件的重新绘制。如果依赖项数组中的任何一项发生变化,组件就会重新绘制。因此,在选择依赖项时,要谨慎考虑。
- useEffect 可以用来管理状态和事件监听。但是,对于一些特定的场景,可以使用更适合的 API,例如 useReducer 或 useMutationEffect。