手写hooks系列第三期,实现常用hook:useUpdateEffect

背景

本文是手写hooks系列第三期,该篇难度:⭐️。

由于React中的useEffect机制,不管什么场景下,useEffect都会在初次渲染期间执行。那么如何实现class组件中的componentDidUpdate呢?

今天带着大家实现一个函数式组件版本的componentDidUpdate

需求

现在要求实现自定义hook:useUpdateEffect,实现后具体用法与useEffect相同,效果与componentDidUpdate相同。

const Test = () => {
  const [num, setNum] = useState(0);

  useUpdateEffect(() => {
    console.log(num, "更新后的num");
  }, [num]);

  return (
    <div>
      {num}
      <button onClick={() => setNum(num + 1)}>add</button>
    </div>
  );
};
复制代码

编码实现

第一步:先定义好输入输出结构。

export const useUpdateEffect: typeof useEffect = (effect, deps) => {
  useEffect(() => {
    return effect();
  }, deps);
};
复制代码

第二步:对初次渲染进行处理,这里的核心是判断初次渲染的时机,如果是初次渲染则不执行传入的effect函数

这里可以通过useRef的方式来判断是否是第一次渲染。

export const useUpdateEffect: typeof useEffect = (effect, deps) => {
  const ref = useRef(true);

  useEffect(() => {
    if (ref.current) {
      ref.current = false; //如果是初次渲染则设置为false
    } else {
      return effect(); //再次渲染时再执行
    }
  }, deps);
};
复制代码

第三步:代码优化。这里其实我们可以把是否是第一次渲染的逻辑,单独提取成一个公共hook:useFirstMountState,这样代码逻辑更清晰。

export function useFirstMountState(): boolean {
  const isFirst = useRef(true);

  if (isFirst.current) {
    isFirst.current = false;

    return true;
  }

  return isFirst.current;
}
复制代码

优化后的useUpdateEffect

export const useUpdateEffect: typeof useEffect = (effect, deps) => {
  const isFirstMount = useFirstMountState(); //是否是第一次渲染

  useEffect(() => {
    if (!isFirstMount) {
      return effect();
    }
  }, deps);
};
复制代码

总结

本文涉及到的所有代码均放在github上的 Demo 中,觉得不错点个赞,嘻嘻❤️❤️❤️。

欢迎大家在评论区留言,给出更优秀的实践!

猜你喜欢

转载自juejin.im/post/7083694236733800461
今日推荐