javascript - 深入React useEffect/useEffect的使用?

标签 javascript reactjs react-redux react-hooks

我正在尝试深入了解 useEffect Hook 。

我想知道何时使用哪种方法以及为什么?

  1. useEffect 不带第二个参数
useEffect(()=>{})
  • useEffect,第二个参数为 []
  • useEffect(()=>{},[])
    
  • useEffect 在第二个参数中传递了一些参数
  • useEffect(()=>{},[arg])
    

    最佳答案

    useEffect(callback);
    
    // Example
    useEffect(() => {
      console.log("executed after render phase");
    
      return () => {
        console.log("cleanup function after render");
      };
    });
    
    • 在每个组件渲染上运行。
    • 通常用于调试,类似于每个函数的函数体执行 渲染:
    const Component = () => {
      callback()
      return <></>;
    };
    

    Note: There is still a difference, in execution time (see the next note). Check this sandbox logs.

    <小时/>
    useEffect(callback,[]);
    
    // Example
    useEffect(() => {
      const fetchUsers = async () => {
        const users = await fetch();
        setUsers(users);
      };
    
      fetchUsers();
      console.log("called on component's mount");
    
      return () => {
        console.log("called on component's unmount");
      };
    }, []);
    
    • 通常用于通过数据获取等方式初始化组件状态。
    • 在组件安装上运行一次
    • cleanup function将在组件卸载时运行。

    陷阱:

    Remember, there is a first render and then a mount.

    Roughly saying, most of bugs regarding useEffect is not knowing how closures works and not paying attention to linting warnings.

    Make sure the array includes all values from the component scope that change over time and that are used by the effect. Otherwise, your code will reference stale values from previous renders - note in React docs.

    <小时/>
    useEffect(callback,[arg]);
    
    // Example
    useEffect(() => {
      console.log({ users });
    
      return () => {
        console.log("user value is changing");
      };
    }, [users]);
    
    • arg 值发生变化时运行。
    • 通常用于在 Prop /状态更改时运行事件。
    • 可以提供多个依赖项:[arg1,arg2,arg3...]
    • 清理函数在 arg 值更改时运行。

    陷阱:

    i.e compares the value of arg from the previous render and the current one, prevArg === arg ? doNothing() : callback().

    • 因为在 Javascript {} === {} || [] === [] 是一个 falsy 语句,如果 arg (在我们的示例中是 users)是一个对象,则回调将在每次渲染时运行。

    • 也在挂载上运行,因为第一次比较总是错误的

    <小时/>

    其他值得注意的要点

    const timeoutIdRef = useRef();
    
    useEffect(() => {
      const timeoutId = timeoutIdRef.current;
      return () => {
      /*
        Using timeoutIdRef.current directly here is not safe
        since you can't guarantee the ref to exists in this point
        (especially when the component unmounts)
      */
        // Should get a lint warning here
        clearTimeout(timeoutIdRef.current); // BAD
    
        // Closure on timeoutId value
        clearTimeout(timeoutId); // GOOD
      };
    }, [arg]);
    
    const isMounted = useRef(false);
    
    useEffect(() => {
      if (isMounted.current) {
        // first mount
      } else {
        isMounted.current = true;
      }
    }, [arg]);
    
    <小时/>

    继续阅读:

    关于javascript - 深入React useEffect/useEffect的使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59841800/

    相关文章:

    javascript - 计数器按钮和新按钮

    javascript - 在 AJAX js 调用中动态分配值

    javascript - 为什么我的合并图像不会出现(ReactJS)?

    javascript - react-redux-react-router v4 url​​,更新但组件不更新

    reactjs - Redux 可以只管理一个 bool 值吗?

    javascript - HTML5本地存储支持的数据

    javascript - 避免回应机器人

    reactjs - 一个组件中的多个表单无法识别表单和初始值属性(redux-form v7.0.4)

    javascript - React Router 4 链接正常工作,但组件未渲染

    javascript - 在 javascript 中循环数组 - 按顺序