修复“无法对已卸载的组件执行React状态更新”错误

时间:2019-06-15 06:51:03

标签: javascript reactjs react-hooks

当我尝试在Web应用程序中推送到新页面时,以下代码给出了控制台错误:

  

警告:无法在已卸载的组件上执行React状态更新。   这是空操作,但它表明应用程序中发生内存泄漏。   要修复,请取消useEffect中的所有订阅和异步任务   清理功能。       在PasswordResetPage中(由Context.Consumer创建)

您会在注释的代码中注意到,我尝试使用INotifyDataErrorInfo,因为这是大多数stackoverflow答案所指向的内容。但是,该错误仍然存​​在。在这种情况下如何使用INotifyDataErrorInfo并摆脱错误?

useEffect

2 个答案:

答案 0 :(得分:1)

查看是否适合您

带有示例的代码SandBox:

https://www.php.net/manual/en/curl.installation.php

const onSubmit = async data => {
    setSubmitting(true)
    await sleep(2000)
    logger.info('form data', data)
    setDone(true)
  }

  useEffect(() => {
    if (isDone) {
      history.push('/confirmation')
    }
  },[isDone]);

在CodeSandbox上工作的代码:

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";

import "./styles.css";

function App() {
  const [user, setUser] = useState(null);

  function doLogin() {
    console.log("Inside do login...");
    setUser("someUserID");
  }

  function doLogout() {
    console.log("Inside do logout...");
    setUser(null);
  }

  return (
    <Router>
      <AllRoutes user={user} doLogin={doLogin} doLogout={doLogout} />
    </Router>
  );
}

function AllRoutes(props) {
  console.log("Rendergin AllRoutes...");
  // console.log(props);
  return (
    <Switch>
      <Route exact path="/" component={Component1} />
      <Route exact path="/comp2" component={Component2} />
    </Switch>
  );
}

function Component1(props) {
  const [isDone, setIsDone] = useState(false);

  useEffect(() => {
    if (isDone) {
      props.history.push("/comp2");
    }
  }, [isDone, props.history]);

  return (
    <React.Fragment>
      <div>Component1</div>
      <button onClick={() => setIsDone(true)}>Submit</button>
    </React.Fragment>
  );
}

function Component2(props) {
  const [goBack, setGoBack] = useState(false);

  useEffect(() => {
    if (goBack) {
      props.history.push("/");
    }
  }, [goBack, props.history]);

  return (
    <React.Fragment>
      <div>Component2</div>
      <button onClick={() => setGoBack(true)}>Go Back</button>
    </React.Fragment>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

答案 1 :(得分:0)

我相信await sleep(2000)可以代替实际的API调用。
API调用以及history.push都是副作用,因此应放在useEffect中。
试试这个:

const PasswordResetPage = ({ history }) => {
  const [formData, setFormData] = useState(null);

  // ...

  const onSubmit = async data => {
    setFormData(data);
  }

  useEffect(() => {
    logger.info('form data', formData);
    sleep(2000).then(() => history.push('/confirmation'););
  }, [formData]);

  // ...
}