实现 useUpdateEffect hook: 改造 useEffect 实现首次渲染时不执行副作用的钩子
最近在过 React 相关面试题的时候,遇到了一个有趣的题目,就是实现 useUpdateEffect hook,刚好前一段时间的工作中遇到了类似的场景,需要 useEffect 在首次渲染的时候不执行副作用,而在后续依赖更新的时候正常执行副作用。和这个面试题一样,当时也是用了useRef
来实现。
让我们先来了解一下useRef:
const refContainer = useRef(initialValue);
useRef
会返回一个可修改的 ref 对象,它的.current
属性会被初始化为传入的参数(initialValue)。这个返回的对象会在这个组件的整个生命周期中保持,意味着只要你不去修改它,他会保持不变(就算在重新渲染之后)。
平时我们最常见使用useRef
的场景是通过引用的方式访问一个子元素或者子组件。这里就不详细介绍这个用法啦。
除此之外,它还可以很方便的保持任何可修改的值,也就是前面我们说到的。
而之所以能够实现这个效果,是因为useRef()
创建了一个纯 js 对象{current: ...}
,并且在每次渲染的时候都返回给你同一个 ref 对象。
因此,我们可以通过 useRef
来判断是否是首次渲染:
import { useRef } from "react";
export function useFirstMountState(): boolean {
const isFirst = useRef(true);
if (isFirst.current) {
isFirst.current = false;
return true;
}
return isFirst.current;
}
然后借助useFirstMountState
来判断是否是首次渲染,并据此判断是否执行副作用:
import { useEffect } from "react";
import { useFirstMountState } from "./useFirstMountState";
const useUpdateEffect: typeof useEffect = (effect, deps) => {
const isFirstMount = useFirstMountState();
useEffect(() => {
if (!isFirstMount) {
return effect();
}
}, deps);
};
export default useUpdateEffect;