深入react useEffect / useEffect 的使用?

IT技术 javascript reactjs react-redux react-hooks
2021-02-08 06:34:25

我试图深入了解useEffect钩子。

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

1.useEffect with no second paraments
 useEffect(()=>{})

2.useEffect with second paraments as []
  useEffect(()=>{},[])

3.useEffect with some arguments passed in the second parameter
 useEffect(()=>{},[arg])
2个回答
useEffect(callback);

// Example
useEffect(() => {
  console.log("executed after render phase");

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

注意:在执行时间方面仍然存在差异(请参阅下一个注释)。检查此沙箱日志


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");
  };
}, []);
  • 通常用于通过数据获取等初始化组件状态。
  • 在组件安装上运行一次
  • 清理功能将在组件的运行卸载

陷阱:

请记住,首先进行渲染然后进行安装。

  • 由于关闭而导致数据过时

粗略地说,大多数错误useEffect不知道闭包如何工作的,也不注意linting 警告

确保数组包含组件作用域中 随时间变化并由效果使用的所有值否则,您的代码将引用之前渲染中的陈旧值-请在 React 文档中注意


useEffect(callback,[arg]);

// Example
useEffect(() => {
  console.log({ users });

  return () => {
    console.log("user value is changing");
  };
}, [users]);
  • arg更改运行
  • 通常用于在props/状态更改时运行事件。
  • 可以提供多个依赖项: [arg1,arg2,arg3...]
  • 清除功能在arg值更改时运行

陷阱:

  • “On Change”是指与 的先前值进行浅比较arg

即比较arg来自前一个渲染和当前渲染的值prevArg === arg ? doNothing() : callback()

  • 因为在 Javascript 中{} === {} || [] === []是一个虚假的语句,如果argusers在我们的例子中)是一个对象,回调将在每次渲染时运行。

  • 也可以在 mount 上运行,因为第一次比较总是假的


其他注意事项

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]);

继续阅读:

“在每次卸载之前运行,无论是最后一次卸载还是在下一次渲染尝试之前”听起来像是有一次“卸载尝试”,但事实并非如此。
2021-03-26 06:34:25
run on every render我会重新表述为runs after each render和清理功能runs before each unmount, either the final unmount or before the next render attempt
2021-03-31 06:34:25
请注意,缺少依赖项会导致过时的闭包以下代码:const [s, setS] = useState(0); useEffect(() => setInterval(() => console.log(s), 1), []);只会记录 0 因为回调在 s 上关闭,即使在每次渲染时重新创建该函数,它也只会在挂载时调用,并且在 s 为 0 时。请参阅多次弹出的问题与这个错误和状态的异步设置被归咎于功能组件,它的根本原因是陈旧的闭包。
2021-04-10 06:34:25
您希望将其中一个答案放入框架中并每周阅读
2021-04-11 06:34:25

如果您熟悉 React 类的生命周期方法,您可以将 useEffect Hook 视为 componentDidMount、componentDidUpdate 和 componentWillUnmount 的组合。

1.useEffect 没有第二个参数:当我们希望在组件刚安装时或已更新时发生某些事情时使用。从概念上讲,我们希望它在每次渲染后发生。

2.useEffect 第二个参数为 [] :当我们希望组件挂载时发生一些事情时使用,如果只在挂载时执行一次。它更接近熟悉的 componentDidMount 和 componentWillUnmount。

3.useEffect 在第二个参数中传递一些参数:当我们希望在 pramter 传递时发生某些事情时使用它,例如。args 在您的情况下发生了变化。

欲了解更多信息。在这里查看:https : //reactjs.org/docs/hooks-effect.html