返回
深入理解useEffect和useLayoutEffect: 源码解析与时机剖析
前端
2023-11-05 02:02:24
useEffect和useLayoutEffect:同宗同源,各司其职
useEffect和useLayoutEffect同为React Hooks,用于处理副作用。它们都有一个回调函数作为参数,该回调函数会在组件渲染后或更新后执行。然而,它们在执行时机上略有不同。
- useEffect会在组件渲染后立即执行,并在组件卸载前执行清理函数(如果有的话)。
- useLayoutEffect会在浏览器完成布局后执行,并在组件卸载前执行清理函数(如果有的话)。
从源码层面比较useEffect和useLayoutEffect
// useEffect源码
export function useEffect(create, deps) {
const nextDeps = useMemo(() => deps, deps && deps.every(isStable));
const hasPrevDeps = nextDeps !== deps;
const prevEffect = useUpdateEffect();
// ...
}
// useLayoutEffect源码
export function useLayoutEffect(create, deps) {
const nextDeps = useMemo(() => deps, deps && deps.every(isStable));
// ...
if (enableLayoutEffect) {
if (!didWarnUseLayoutEffectForUI && warnAboutLayoutEffects) {
didWarnUseLayoutEffectForUI = true;
console.error(
'Warning: useLayoutEffect does nothing on the server, because its effect ' +
'cannot be inspected until after rendering. Consider server-side rendering ' +
'or switching to useEffect.',
);
}
}
// ...
}
从源码中可以看出,useEffect和useLayoutEffect在实现上非常相似,但也有细微差别。
- useEffect使用
useUpdateEffect
钩子来管理效果的创建和销毁,而useLayoutEffect使用useLayoutEffectImpl
钩子。 - useEffect在组件渲染后立即执行,而useLayoutEffect会在浏览器完成布局后执行。
- useEffect可以在服务器端渲染中使用,而useLayoutEffect不能。
类组件生命周期与this.setState的callback的执行时机
在类组件中,有几个常用的生命周期方法,分别是:
componentDidMount
:在组件首次挂载后调用。componentDidUpdate
:在组件更新后调用,但不适用于首次挂载。componentWillUnmount
:在组件卸载前调用。
this.setState的callback会在组件更新后调用,但不适用于首次挂载。
useEffect和useLayoutEffect与类组件生命周期的对应关系
useEffect和useLayoutEffect与类组件生命周期的对应关系如下:
React Hook | 类组件生命周期 | 执行时机 |
---|---|---|
useEffect | componentDidMount, componentDidUpdate | 组件渲染后立即执行 |
useLayoutEffect | componentDidMount, componentDidUpdate | 浏览器完成布局后执行 |
useEffect和useLayoutEffect的最佳实践
在使用useEffect和useLayoutEffect时,有一些最佳实践需要遵循:
- 尽量使用useEffect,只有在需要在浏览器完成布局后执行副作用时才使用useLayoutEffect。
- 在useEffect和useLayoutEffect中,尽量使用函数式更新,避免使用类组件中的this.setState。
- 在useEffect和useLayoutEffect的清理函数中,尽量避免执行昂贵的操作,比如网络请求或DOM操作。
结语
通过本文的深入剖析,我们对useEffect和useLayoutEffect有了更深入的理解。我们了解了它们在执行时机上的细微差别,也探讨了它们与React生命周期以及this.setState回调的执行时机之间的关系。希望这些知识能够帮助你在实际开发中更加高效地使用React Hooks。