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

时间:2020-04-09 19:36:31

标签: javascript reactjs web-component

我制作了一个登录表单,以便当某人成功登录时,服务器发送用户信息(名称,电子邮件,ID),并且某些页面状态也会相应更改(例如路由,用户对象),但是每当我登录时一切正常好吧,但是我在控制台中看到一条错误消息:

index.js:1 Warning: 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 the componentWillUnmount method.
    in Login (at App.js:226)

这真的使我感到困惑,因为该应用程序仍然可以正常运行,并且idk为什么我遇到此错误。

app.js的render():

  render() {

    if (this.state.route === 'login') {
      return <Login loadUser={this.loadUser} routeChange={this.routeChange} /> //this is line 226 at app.js

    } else if (this.state.route === 'register') {
      return <Register loadUser={this.loadUser} routeChange={this.routeChange} />

    } else {
      return (
        <div>
          {/* The rest of the app's home components */}
        </div>
      )
    }

login.js:

    class Login extends Component {
    constructor(props) {
        super(props);
        this.state = {
            email: "",
            password: "",
            loading: false
        }
    }

    handleChange = (e) => {
        this.setState({ [e.target.name]: e.target.value })

    }

    handleClick = () => {

        this.setState({ loading: true })
        fetch('myApi/login', {
            method: 'post',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                email: this.state.email,
                password: this.state.password
            })
        })
            .then(response => response.json())
            .then(user => {
                if (user.id) {
                    this.props.routeChange('home');

                    this.props.loadUser(user);
                    //localStorage.setItem('user', JSON.stringify(user));
                    this.setState({ loading: false })
                }
            })
    }

    render() {
        return (
            <div className="container">
                <div className="row">
                    <div className="col-sm-9 col-md-7 col-lg-5 mx-auto">
                        <div className="card card-signin my-5">
                            <div className="card-body">
                                <h5 className="card-title text-center">Sign In</h5>
                                <form onSubmit={(e) => e.preventDefault()} className="form-signin">
                                    <div className="form-label-group">
                                        <input onChange={this.handleChange} name="email" type="email" id="inputEmail" className="form-control" placeholder="Email address" autoFocus />
                                        <label htmlFor="inputEmail">Email address</label>
                                    </div>
                                    <div className="form-label-group">
                                        <input onChange={this.handleChange} name="password" type="password" id="inputPassword" className="form-control" placeholder="Password" />
                                        <label htmlFor="inputPassword">Password</label>
                                    </div>
                                    <div className="custom-control custom-checkbox mb-3">
                                        <input type="checkbox" className="custom-control-input" id="customCheck1" />
                                        <label className="custom-control-label" htmlFor="customCheck1">Remember password</label>
                                    </div>
                                    <button onClick={this.handleClick} className="btn btn-lg btn-primary btn-block text-uppercase">Sign in</button>
                                    <hr className="my-4" />
                                    <h6 onClick={() => this.props.routeChange('register')} style={{ textAlign: 'center', cursor: 'pointer' }}>Register instead</h6>
                                </form>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
}

2 个答案:

答案 0 :(得分:2)

问题是这种thenable条件,在更改路由后设置状态时。 记住 状态更新是异步的,并且在每个新的渲染周期之前发生。

if (user.id) {
  this.props.routeChange('home');
  this.props.loadUser(user);
  //localStorage.setItem('user', JSON.stringify(user));
  this.setState({ loading: false }) // <-- error since component unmounted!!
}

将加载状态恢复为false应该解决警告:

if (user.id) {
  this.props.routeChange('home');
  this.props.loadUser(user);
}

编辑要真正正确地解决此问题,请将路由更改移至生命周期功能,这样,如果登录无效或用户对象没有{{ 1}}属性。

id

答案 1 :(得分:1)

我认为问题实际上出在您的loadUser函数中。你能分享吗?您是否要在loadUser函数中更改页面?

componentDidMount() {
   this.isMounted = true;
}

componentWillUnmount() {
   this.isMounted = false;
}

handleClick = () => {
fetch('myApi/login', {
    method: 'post',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
        email: this.state.email,
        password: this.state.password
    })
})
    .then(response => response.json())
    .then(user => {
        if (user.id) {
            if (this.isMounted) this.setState({ this.state..., loading: false });
            if (this.isMounted) this.props.loadUser(user);
            if (this.isMounted) this.props.routeChange('home');
        }
    })
}