简体   繁体   English

React setState只能更新已安装或安装的组件

[英]React setState can only update a mounted or mounting component

I am getting the following warning 我收到以下警告

"Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the ContactPage component." “警告:setState(...):只能更新已安装或安装的组件。这通常意味着您在未安装的组件上调用了setState()。这是一个无操作。请检查ContactPage组件的代码。”

When I initially go to the contact page the firs time it is fine. 当我最初进入联系页面时,第一次就可以了。 Then if I navigate off the page and go back the warning is thrown. 然后,如果我离开页面并返回,则会抛出警告。

Contact page component : 联系页面组件:

import React, { Component, PropTypes } from 'react';
import AppStore from '../../stores/AppStore';
import AppActions from '../../actions/AppActions';
import DataContent from './DataContent';

const title = 'Contact Us';


class ContactPage extends Component {

    constructor(props) {
        super(props);
        this.state = AppStore.getState();
        AppActions.getData();
    }

  static contextTypes = {
    onSetTitle: PropTypes.func.isRequired,
  };

  componentWillMount() {
    this.context.onSetTitle(title);
    AppStore.listen(this.onChange.bind(this));
}

componentWillUnmount() {
    AppStore.unlisten(this.onChange.bind(this));
}

onChange(state) {
    this.setState(state);
}

renderData() {
    return this.state.data.map((data) => {
        return (
            <DataContent key={data.id} data={data} />
        )
    })
}

  render() {
    return (
      <div className={s.root}>
        <div className={s.container}>
          <h1>{title}</h1>
          <div>
              { this.renderData() }
          </div>
        </div>
      </div>
    );
}

}

export default ContactPage;

When I put debuggers in, on load of contact page it hits componentWillMount(). 当我把调试器放入,在加载联系页面时它会命中componentWillMount()。 When I leave the contact page it hits componentWillUnmount(). 当我离开联系页面时,它会命中componentWillUnmount()。 When I navigate back to the page it hits componentWillMount() again and then throws the error when it hits the onChange(state) function. 当我导航回页面时,它会再次命中componentWillMount(),然后在遇到onChange(state)函数时抛出错误。

The issue is that the listener of the previous component instance is still registered. 问题是前一个组件实例的监听器仍然是已注册的。 And because the previous instance isn't mounted anymore, you get that error. 并且因为先前的实例不再安装,所以您会收到该错误。

.bind always returns a new function. .bind总是返回一个函数。 So if you do 所以,如果你这样做

AppStore.unlisten(this.onChange.bind(this));

then you are trying to remove a listener that doesn't exist (which fails of course). 那么你试图删除一个不存在的监听器(当然失败了)。 It does not remove the listener you registered with AppStore.listen(this.onChange.bind(this)) 不会删除您注册的监听器AppStore.listen(this.onChange.bind(this))


To solve this, you should bind the handler once in the constructor: 要解决这个问题,您应该在构造函数中绑定处理程序一次

this.onChange = this.onChange.bind(this);

and then use AppStore.listen(this.onChange) and AppStore.unlisten(this.onChange) . 然后使用AppStore.listen(this.onChange)AppStore.unlisten(this.onChange)

Before the change, state check component is mounted. 在更改之前,将安装状态检查组件。

render() {
   return (
     <div ref="root" className={s.root}>
       // ----
     </div>
   )};

 onChange(state) {
   if(this.refs.root) {
     this.setState(state);
   }
 }

I think this will help to you. 我想这会对你有所帮助。

In your case add a ref to your root div and check the ref value before you call setState. 在您的情况下,在您调用setState之前,将ref添加到根div并检查ref值。

Your onChange method should looks like this: 你的onChange方法应如下所示:

onChange(state) {
    this.refs.yourRef ? this.setState(state) : null;    
}

I was struggling with this issue as well for quite a while. 我也在这个问题上苦苦挣扎了很长一段时间。

What solved for me was to do as @Felix Kling proposed but also make sure my callback function was declared within the component's class, otherwise you're not able to use the this prefix, wich was apparently what did the trick for me. 为我解决的问题是@Felix Kling提出的做法,但也要确保我的回调函数在组件的类中声明,否则你无法使用this前缀,这显然对我有什么作用。

Here is an example of what I mean: 这是我的意思的一个例子:

Legal, but doesn't work 合法,但不起作用

function onChange() { 
  this.setState({ MyState: newState })
}

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    onChange = onChange.bind(this);
  }

  componentDidMount() {
    window.addEventListener('resize', onChange);
  }

  componentWillUnmount() {
    window.removeEventListener('resize', onChange);
  }

  render() { ... }
}

Works 作品

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.onChange = this.onChange.bind(this);
  }

  onChange() { 
    this.setState({ MyState: newState })
  }

  componentDidMount() {
    window.addEventListener('resize', this.onChange);
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.onChange);
  }

  render() { ... }
}

Hope it helps anyone else facing this problem. 希望它能帮助其他任何人面对这个问题。 :) :)

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

相关问题 React setstate只能在重新渲染时更新已安装或安装的组件 - React setstate can only update a mounted or mounting component — on rerender React JS setState(…):只能更新已安装或正在安装的组件 - React JS setState(…): Can only update a mounted or mounting component React-setState(…)只能更新已安装或正在安装的组件 - React - setState(…) Can only update a mounted or mounting component React-setState(…):只能更新已安装或正在安装的组件 - React - setState(…): Can only update a mounted or mounting component 反应警告:setState(…)只能更新已安装或正在安装的组件 - React Warning: setState(…) Can only update a mounted or mounting component 警告:setState(…):只能更新已安装或正在安装的组件 - Warning react : setState(…): Can only update a mounted or mounting component React:setState只能更新已安装或安装的组件 - React: setState can only update a mounted or mounting component 反应警告setState(…):只能更新已安装或正在安装的组件 - React warning setState(…): Can only update a mounted or mounting component setState只能更新已安装或安装的组件 - setState Can only update a mounted or mounting component setState(…):只能更新已安装或正在安装的组件 - setState(…): Can only update a mounted or mounting component
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM