Javascript “固定”;Can';t对未安装的组件执行React状态更新“;错误

Javascript “固定”;Can';t对未安装的组件执行React状态更新“;错误,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,当我尝试在web应用程序中推送到新页面时,下面的代码给出了一个控制台错误: 警告:无法对已卸载的组件执行React状态更新。 这是一个no-op,但它表示应用程序中存在内存泄漏。 若要修复,请取消useEffect中的所有订阅和异步任务 清理功能。 在PasswordResetPage中(由Context.Consumer创建) 您会注意到,在注释掉的代码中,我尝试使用useffect,因为这是大多数stackoverflow答案所指向的。但是,错误仍然存在。如何在此上下文中使用history.

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

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

您会注意到,在注释掉的代码中,我尝试使用
useffect
,因为这是大多数stackoverflow答案所指向的。但是,错误仍然存在。如何在此上下文中使用
history.push
,并消除错误

import React, { useState /* , useEffect */ } from 'react'
import useForm from 'react-hook-form'
import Logo from '../assets/images/logo-icon-orange.png'
import TextInput from '../components/TextInput'
import Footer from '../components/Footer'
import AnimatedButton from '../components/AnimatedButton'
import logger from '../logger'
import { sleep } from '../utils/promise'
import PasswordResetSchema from './validation/PasswordResetSchema'

const PasswordResetPage = ({ history }) => {
  const [isSubmitting, setSubmitting] = useState(false)
  // const [isDone, setDone] = useState(false)
  const { register, handleSubmit, errors } = useForm({
    validationSchema: PasswordResetSchema,
  })

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

  // useEffect(() => {
  //   if (isDone) {
  //     history.push('/confirmation')
  //   }
  // })


  return (
    <form onSubmit={handleSubmit(onSubmit)} noValidate>
      <div className="text-center mb-4">
        <img className="mb-4" src={Logo} alt="Striver" width={72} />
        <h1 className="h3 mb-3 font-weight-normal">Password reset</h1>
        <p>Enter your email address below and we will send you instructions on how you can reset your password.</p>
      </div>

      <div className="form-label-group">
        <TextInput type="email" id="email" register={register} label="Email address" errors={errors} />
      </div>

      <AnimatedButton actionTitle="Next" isSubmitting={isSubmitting} />
      <Footer />
    </form>
  )
}

export default PasswordResetPage
从“React”导入React,{useState/*,useffect*/}
从“react hook form”导入useForm
从“../assets/images/Logo icon orange.png”导入徽标
从“../components/TextInput”导入TextInput
从“../components/Footer”导入页脚
从“../components/AnimatedButton”导入AnimatedButton
从“../logger”导入记录器
从“../utils/promise”导入{sleep}
从“./validation/PasswordResetSchema”导入PasswordResetSchema
const PasswordResetPage=({history})=>{
常量[isSubmitting,setSubmitting]=使用状态(false)
//const[isDone,setDone]=useState(false)
常量{register,handleSubmit,errors}=useForm({
validationSchema:PasswordResetSchema,
})
const onSubmit=异步数据=>{
设置提交(真)
等待睡眠(2000年)
logger.info('formdata',data)
//设置完成(真)
history.push(“/confirmation”)
}
//useffect(()=>{
//中频(isDone){
//history.push(“/confirmation”)
//   }
// })
返回(
密码重置
在下面输入您的电子邮件地址,我们将向您发送有关如何重置密码的说明

) } 导出默认密码重置页
看看这是否适合您:

使用工作示例编写沙箱代码:

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

import React,{useState,useffect}来自“React”;
从“react dom”导入react dom;
从“react Router dom”导入{BrowserRouter as Router,Route,Switch};
导入“/styles.css”;
函数App(){
const[user,setUser]=useState(null);
函数doLogin(){
log(“内部登录…”);
setUser(“someUserID”);
}
函数doLogout(){
日志(“内部做注销…”);
setUser(空);
}
返回(
);
}
功能所有路线(道具){
日志(“renderginallroutes…”);
//控制台日志(道具);
返回(
);
}
功能组件1(道具){
const[isDone,setIsDone]=useState(false);
useffect(()=>{
中频(isDone){
道具历史推送(“/comp2”);
}
},[isDone,道具历史];
返回(
组件1
setIsDone(true)}>Submit
);
}
功能组件2(道具){
const[goBack,setGoBack]=useState(false);
useffect(()=>{
if(goBack){
props.history.push(“/”);
}
},[goBack,道具,历史];
返回(
组件2
setGoBack(true)}>返回
);
}
const rootElement=document.getElementById(“根”);
render(,rootElement);

我相信
等待睡眠(2000)
是实际API调用的替代品。
API调用以及
history.push
都是副作用,因此应该放在
useffect

试试这个:

const PasswordResetPage=({history})=>{
const[formData,setFormData]=useState(null);
// ...
const onSubmit=异步数据=>{
setFormData(数据);
}
useffect(()=>{
logger.info('formData',formData);
sleep(2000)。然后(()=>history.push('/confirmation');
},[formData]);
// ...
}

由于完整性,我接受了这个答案,但根本原因是我正在使用的表单库。干杯@AndreGallo我也在使用react hook表单,并通过重置来解决这个问题。你是怎么解决的?@Shay我在那时更新到了最新版本time@AndreGallo谢谢,这并不能解决我的问题。但至少排除了一种可能性。
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);