掌握React的useEffect:提高开发效率的4个技巧

目录
文章目录隐藏
  1. 1. 清除副作用
  2. 2. 获取初始值
  3. 3. 只监听数据的变化
  4. 4. 获取 DOM 元素
  5. 5. 总结

掌握 React 的 useEffect:提高开发效率的 4 个技巧

我们知道 React 的 useEffect 有一些常规用法:

  1. 在组件挂载时执行一次,能够获取到真实的 dom 元素;
  2. 组件销毁时执行回调,可以清除和重置数据;

如:

const App = () => {
  useEffect(() => {
    if (open && values) {
      form.setFieldsValue(values);

      return () => form.resetFields();
    }
  }, [open, values]);
};

useEffect的回调会在组件挂载完成时执行一次,后续若依赖项改变,则回调会再次执行。同时在组件卸载时可以清除副作用。基于这个特性,我们实现一些特定的功能。

1. 清除副作用

如定时器、JavaScript 原生事件等,在组件卸载时需要取消定时器和卸载原生事件。

const App = () => {
  useEffect(() => {
    const timer = setInterval(() => {
      console.log(Date.now());
    }, 1000);

    return () => clearInterval(timer);
  }, []);

  useEffect(() => {
    const listener = () => {
      console.log(window.scrollX, window.scrollY);
    };
    window.addEventListener("scroll", listener, false);

    return () => window.removeEventListener("scroll", listenter);
  }, []);
};

若没有及时取消,在组件多次渲染时,可能会产生多个定时器或者绑定多个事件。

2. 获取初始值

我在自定义一些稍微复杂的 Form 表单组件时,经常会用到这个功能。

Ant Design的自定义 Form 表单时,Form 组件会把 value 和 onChange 传给自定义组件内,我们再进行获取。但因为是异步获取数据,form 表单的初始化有延迟,我们并不能马上获取到数据。因此可以监听传入的 value,当获取到 value 后就不再处理该数据。

const InputApp = ({ value: initValue, onChange }) => {
  const [value, setValue] = useState(initValue);
  const initedRef = useRef(false); // 是否获取到了初始值

  useEffect(() => {
    if (initedValue && !initedRef.current) {
      // 已经有值并且还没初始操作
      initedRef.current = true;
      setValue(initedValue);
    }
  }, [initValue]);
};

3. 只监听数据的变化

useEffect()会在组件初始化时执行一次回调函数,然后在依赖项发生变化时,也会执行回调函数。

但是,我们并不希望在组件初始化时执行回调函数,只想监听依赖的变化。我们可以像第 2 小节中那样,用一个标记来表示。

我们认为第一次执行,就是初始时执行;后续是依赖项变化时导致的

因此我们把第一次执行跳过即可。

const App = (props) => {
  const firstedRef = useRef(false); // 初始化的回调是否已执行

  useEffect(() => {
    if (!firstedRef.current) {
      firstedRef.current = true;
      return;
    }
    console.log("props changed", props);
  }, [props]);
};

4. 获取 DOM 元素

无论是使用 ref 属性useRef() ,还是原生的 js 方法,获取 DOM 元素,在 useEffect() 中都能保证获取到真实的 DOM 元素。如果是异步获取数据后再渲染 DOM 元素,可以在依赖项中监听对应的数据。

const App = () => {
  const domRef = useRef(null);

  useEffect(() => {
    // 通过 ref 属性 和 useRef() 获取 dom 元素
    console.log(domRef.current);

    // 通过原生的 js 的方法获取 dom 元素
    console.log(document.getElementById("title"));
  }, []);

  return (
    <div ref={domRef}>
      <div id="title">前端博客</div>
    </div>
  );
};

若是通过异步获取数据后,然后再渲染的页面,可以监听相应的数据。

import useSWR from "swr";

const App = () => {
  const itemRefs = useRef([]);

  const { data } = useSWR("/api", async () => {
    const response = await fetch("/api");

    return res.json();
  });

  useEffect(() => {
    if (data) {
      // 在这里,你可以访问 itemRefs.current 数组,它包含了所有的 DOM 元素
      itemRefs.current.forEach((item, index) => {
        console.log(`Item ${index}:`, item);
      });
    }
  }, [data]);

  return (
    <div>
      {data?.map((item) => (
        <div key={item.id} ref={(ele) => itemRefs.current.push(ele)}></div>
      ))}
    </div>
  );
};

5. 总结

在 React 中,使用 useEffect() 可以实现一些特殊的功能。如清除副作用、获取初始值、只监听数据的变化、获取 DOM 元素等。useEffect() 是 React 提供的一个钩子函数,用于在组件渲染后执行副作用操作。副作用操作包括订阅数据源、手动修改 DOM、网络请求等。通过传入一个回调函数给 useEffect(),可在组件的生命周期中执行特定的逻辑。可以传入一个空数组作为第二个参数,仅在组件挂载和卸载时执行一次,用于清除副作用。另外,可以传入一个依赖数组作为第二个参数,仅当依赖项发生变化时才执行回调函数。这样可以优化性能,避免不必要的重复执行。通过 useEffect(),我们可以更加灵活地控制组件的行为,实现各种功能需求。

「点点赞赏,手留余香」

1

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系maynote@foxmail.com处理
码云笔记 » 掌握React的useEffect:提高开发效率的4个技巧

发表回复