繁体   English   中英

React useState 导致“无法在未安装的组件上执行 React 状态更新..”错误

[英]React useState causing “Can't perform a React state update on an unmounted component..” error

我是 React/Node 的新手,正在从事一个学习项目。 这是一个将用户(自由职业者)与非营利公司联系起来的平台。 当用户登录时,他们可以转到 UserConnections 页面以查看他们连接的所有公司。

这工作正常,但我也收到警告Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function. Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function. 此外,当我访问此组件时,命令行开始以极快的速度无休止地吐出连接消息。

我认为问题来自 UserConnections 组件中使用的这个useEffect 这段代码写起来很痛苦,需要这里多人的帮助才能写出来。 我很犹豫要不要碰它。

useEffect(() => {        
      const comps = connections.map((c) => VolunteerApi.getCurrentCompany(c));
      Promise.all(comps).then((comps => setCompanies(comps)));
    }    
  }, [connections]);  

我试着像这样重写它:

useEffect(() => {
    let isMounted = true;
    const comps = connections.map((c) => VolunteerApi.getCurrentCompany(c));
    if (isMounted) {
      Promise.all(comps).then((comps => setCompanies(comps)));
    }
    return () => { isMounted = false };        
  }, [connections]);

但这根本没有改变任何事情。

如何更改此代码以避免内存泄漏而不影响此功能的预期用途? 下面是这个组件的代码。 感谢您的任何帮助。

用户连接

function UserConnections() {
  const { currentUser, connectionHandles } = useContext(UserContext);
  const connections = currentUser.connections.concat(connectionHandles);
  const [companies, setCompanies] = useState([]);

  useEffect(() => {
    const comps = connections.map((c) => VolunteerApi.getCurrentCompany(c));
    Promise.all(comps).then((comps => setCompanies(comps)));
  }, [connections]);

  if (!companies || companies.length == 0) {
    return (
      <div>
        <p>You have no connections</p>
      </div>
    )
  } else {
    return (
      <div>
        {companies && companies.map(c => (
          <CompanyCard
            key={c.companyHandle}
            companyHandle={c.companyHandle}
            companyName={c.companyName}
            country={c.country}
            numEmployees={c.numEmployees}
            shortDescription={c.shortDescription}
          />
        ))}
      </div>
    );
  }
};

您在重写时几乎正确( isMounted !) - isMounted检查需要进入then

代替:

    if (isMounted) {
      Promise.all(comps).then((comps => setCompanies(comps)));
    }

你这样写:

      Promise.all(comps).then(comps => isMounted && setCompanies(comps));

这也只是一个警告。 你应该修复它,是的,但这不是疯狂的关键。

编辑:

无限循环问题:

const connections = currentUser.connections.concat(connectionHandles);

每次重新渲染组件(调用setCompanies )时,连接useEffect发生变化,因此useEffect引用会发生变化。 修复它的方法是使用connectionHandlescurrentUser作为效果的依赖项,并在效果内部移动connections ,例如:

function UserConnections() {
  const { currentUser, connectionHandles } = useContext(UserContext);
  const [companies, setCompanies] = useState([]);

  useEffect(() => {
    let isMounted = true;
    // move connections inside the effect
    const connections = currentUser.connections.concat(connectionHandles);
    const comps = connections.map((c) => VolunteerApi.getCurrentCompany(c));
    Promise.all(comps).then((comps => isMounted && setCompanies(comps)));
    return () => { isMounted = false };
  }, [currentUser,connectionHandlers]);


...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM