错误:无法对未安装的组件执行 React 状态更新

Posted

技术标签:

【中文标题】错误:无法对未安装的组件执行 React 状态更新【英文标题】:Error : Can't perform a React state update on an unmounted component 【发布时间】:2021-07-07 08:49:03 【问题描述】:

这是完全错误

警告:无法对未安装的组件执行 React 状态更新。 这是一个空操作,但它表明您的应用程序中存在内存泄漏。 要修复,请取消 useEffect 中的所有订阅和异步任务 清理功能。 在注册页面

这是我的 siguppage.js 文件

import React,  useState  from 'react'
import  withFirebase  from '../firebase/Context'
import  useHistory  from 'react-router-dom'
import  compose  from 'recompose'
import withAuthUser from '../UserData/withAuthUser'

const SignUpPage = (props) => 
    const [Email, setEmail] = useState('')
    const [PasswordOne, setPasswordOne] = useState('')
    const [PasswordTwo, setPasswordTwo] = useState('')
    const [UserName, setUserName] = useState('')
    const [error, setError] = useState('')
    let history = useHistory()
    const [AuthUser, setAuthUser] = props.AuthUser()

    const onSubmit = () => 
        props.firebase
            .createUserWithEmailAndPassword(Email, PasswordOne)
            .then((authUser) => 
                history.push('/home')
                setAuthUser(authUser)
            )
            .catch((error) => 
                setError(error)
                console.log(error)
            )
    

    const IsInvalid =
        Email === '' ||
        PasswordOne === '' ||
        PasswordTwo === '' ||
        UserName === '' ||
        PasswordTwo !== PasswordOne

    return (
        <div>
            <h1>Sign Up</h1>

            <input
                type='text'
                placeholder='UserName'
                value=UserName
                onChange=(UserName) => 
                    const  value  = UserName.target
                    setUserName(value)
                
            ></input>
            <input
                type='text'
                placeholder='email'
                value=Email
                onChange=(Email) => 
                    const  value  = Email.target
                    setEmail(value)
                
            ></input>
            <input
                type='password'
                placeholder='PasswordOne'
                value=PasswordOne
                onChange=(pass) => 
                    const  value  = pass.target
                    setPasswordOne(value)
                
            ></input>
            <input
                type='password'
                placeholder='PasswordTwo'
                value=PasswordTwo
                onChange=(pass) => 
                    const  value  = pass.target
                    setPasswordTwo(value)
                
            ></input>
            <button disabled=IsInvalid onClick=onSubmit type='submit'>
                Submit
            </button>

            error && <p>error.message</p>
        </div>
    )


export default compose(withFirebase, withAuthUser)(SignUpPage)

我为此使用了 HOC,我通过类似这样的 withAuthUser 传递了props.AuthUser

const withAuthUser = (Component) => (props) => 
    return (
        <AuthUserContext.Consumer>
            (AuthUser) => <Component ...props AuthUser=AuthUser></Component>
        </AuthUserContext.Consumer>
    )

AuthUser 是一个函数

export const Value = () => 
    const [AuthUser, setAuthUser] = useState(null)
    return [AuthUser, setAuthUser]

我将此函数传递给主 index.js 中的 Provider usign 上下文

所以我试图通过调用 props.setAuthUser 来更新 AuthUser 的状态,但它给出了这个错误..

【问题讨论】:

你能把你的代码放到codesandbox吗,因为这样很难理解 ok..把它放到发送箱 【参考方案1】:

当您在离开屏幕后尝试更新屏幕内的状态时会出现此错误。为了解决这个问题,我们需要一个使用 useEffect 钩子的清理函数

所以你的SignupPage.js 应该是这样的

import React,  useEffect, useState  from "react";
import  withFirebase  from "../firebase/Context";
import  useHistory  from "react-router-dom";
import  compose  from "recompose";
import withAuthUser from "../UserData/withAuthUser";

const SignUpPage = (props) => 
  const [Email, setEmail] = useState("");
  const [PasswordOne, setPasswordOne] = useState("");
  const [PasswordTwo, setPasswordTwo] = useState("");
  const [UserName, setUserName] = useState("");
  const [error, setError] = useState("");
  let history = useHistory();
  const [AuthUser, setAuthUser] = props.AuthUser();

  useEffect(() => 
    return () => ;
  , []);

  const onSubmit = () => 
    props.firebase
      .createUserWithEmailAndPassword(Email, PasswordOne)
      .then((authUser) => 
        history.push("/home");
        setAuthUser(authUser);
      )
      .catch((error) => 
        setError(error);
        console.log(error);
      );
  ;

  const IsInvalid =
    Email === "" ||
    PasswordOne === "" ||
    PasswordTwo === "" ||
    UserName === "" ||
    PasswordTwo !== PasswordOne;

  return (
    <div>
      <h1>Sign Up</h1>

      <input
        type="text"
        placeholder="UserName"
        value=UserName
        onChange=(UserName) => 
          const  value  = UserName.target;
          setUserName(value);
        
      ></input>
      <input
        type="text"
        placeholder="email"
        value=Email
        onChange=(Email) => 
          const  value  = Email.target;
          setEmail(value);
        
      ></input>
      <input
        type="password"
        placeholder="PasswordOne"
        value=PasswordOne
        onChange=(pass) => 
          const  value  = pass.target;
          setPasswordOne(value);
        
      ></input>
      <input
        type="password"
        placeholder="PasswordTwo"
        value=PasswordTwo
        onChange=(pass) => 
          const  value  = pass.target;
          setPasswordTwo(value);
        
      ></input>
      <button disabled=IsInvalid onClick=onSubmit type="submit">
        Submit
      </button>

      error && <p>error.message</p>
    </div>
  );
;

export default compose(withFirebase, withAuthUser)(SignUpPage);

试试这个并告诉我。

【讨论】:

我能够解决错误,但状态没有更新。我在问题中添加了一个代码沙箱链接,请查看...【参考方案2】:

您正在尝试在未安装的组件上设置状态。

const onSubmit = () => 
  props.firebase
    .createUserWithEmailAndPassword(Email, PasswordOne)
    .then((authUser) => 
      history.push("/home"); //This causes the current component to unmount
      setAuthUser(authUser); //This is an async action, you are trying to set state on an unmounted component.
    )
    .catch((error) => 
      setError(error);
      console.log(error);
    );
;

【讨论】:

【参考方案3】:

未安装的组件是您的 SignUpPage 组件。找到在挂载上使用它的组件时停止 onSubmit 的方法。首先,当使用这个函数和这个 onSubmit 的组件挂载时运行一个清理函数,所以将清理函数放在 onSubmit 中并返回它,这样在 useEffect 中返回一个值并且该值是一个函数,然后当使用的组件这个 useEffect 它触发返回的清理函数。您可以创建诸如 AbortController() 之类的东西来捕获错误并更新状态。

【讨论】:

这没有提供问题的答案。一旦你有足够的reputation,你就可以comment on any post;相反,provide answers that don't require clarification from the asker。 - From Review

以上是关于错误:无法对未安装的组件执行 React 状态更新的主要内容,如果未能解决你的问题,请参考以下文章

反应钩子。无法对未安装的组件执行 React 状态更新

警告:无法对未安装的组件执行 React 状态更新

“警告:无法对未安装的组件执行 React 状态更新。” [关闭]

路由器事件在构造函数上使用时会导致错误警告:无法对未安装的组件执行 React 状态更新

警告:无法对未安装的组件(多个组件)执行 React 状态更新

React-Apollo - 查询 - renderProp:反应警告:无法对未安装的组件执行反应状态更新