我不明白useEffect在这里发生了什么

时间:2020-08-14 17:57:11

标签: reactjs

如果在token中找到了localStorage,我正在尝试加载用户。当然,我在代码中的任何地方都没有将true分配给isAuthenticated,但是我的问题是,是否要执行以下操作……

const [isAuthenticated, setIsAuthenticated] = useState(false);

  useEffect(() => {
    let mounted = true;
    setIsAuthenticated(false);
    const loadUser = async () => {
      await fetch('http://localhost:5000/api/auth', {
        method: 'GET',
        headers: {
          'x-auth-token': localStorage.token,
        },
      });

      if (!mounted) {
        setIsAuthenticated(false);
      }
    };

    loadUser();

    return () => {
      mounted = false;
    };
  }, []);

我没有收到这个问题... 警告:无法在已卸载的组件上执行React状态更新。这是空操作,但它表明应用程序中发生内存泄漏。要修复,请取消使用useEffect清理功能中的所有订阅和异步任务。

但是,如果我要更改

if (!mounted) {
  setIsAuthenticated(false);
}

if (!mounted) {
  setIsAuthenticated(true);
}

我确实收到了警告,我只是想知道为什么会发生这种情况,以便我知道在出现这种情况时如何正确处理它。

2 个答案:

答案 0 :(得分:1)

警告是:

警告:无法在已卸载的组件上执行React状态更新

您可以调用状态设置器,但不能更改状态,因为这将导致重新渲染,但由于组件已卸载,因此React无法重新渲染,请参见以下代码:

const Working = () => {
  const [value, setValue] = React.useState(true);
  React.useEffect(() => {
    //not changing the value
    setTimeout(() => setValue(true), 100);
  });
  return `value is: ${value}`;
};
const Warning = () => {
  const [value, setValue] = React.useState(true);
  React.useEffect(() => {
    //changing the value causes re render
    //  but component was unmounted by App
    setTimeout(() => setValue(false), 100);
  });
  return `value is: ${value}`;
};
const App = () => {
  const [remount, setRemount] = React.useState(true);
  const causeWarning = () => {
    setRemount(false);
    Promise.resolve(true)
      .then(setRemount)
      .then(() => setRemount(false));
  };
  return (
    <div>
      <button onClick={causeWarning}>cause warnig</button>
      {remount && <Working />}
      {remount && <Warning />}
    </div>
  );
};

卸载组件时最好不要调用状态设置器:

if (mounted) {
  setIsAuthenticated(false);
}

警告内容:

这是空操作,但是它表明您的应用程序中存在内存泄漏。

意味着您可以

答案 1 :(得分:0)

你必须这样做

    useEffect(() => {
    let mounted = true;
    setIsAuthenticated(false);
    const loadUser = async () => {
      await fetch('http://localhost:5000/api/auth', {
        method: 'GET',
        headers: {
          'x-auth-token': localStorage.token,
        },
      }).then(()=> {
          if (!mounted) {
              setIsAuthenticated(true);
               }
            });
       };

    loadUser();

    return () => {
      mounted = false;
    };
  }, []);