React setState 只能更新一个挂载或挂载的组件

IT技术 javascript reactjs
2021-05-18 11:04:29

我收到以下警告

“警告:setState(...):只能更新已安装或正在安装的组件。这通常意味着您在未安装的组件上调用了 setState()。这是一个空操作。请检查 ContactPage 组件的代码。”

当我第一次进入联系页面时,它很好。然后,如果我离开页面并返回,则会抛出警告。

联系页面组件:

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;

当我将调试器放入时,在加载联系页面时它会点击 componentWillMount()。当我离开联系页面时,它会点击 componentWillUnmount()。当我导航回页面时,它再次点击 componentWillMount() ,然后在点击 onChange(state) 函数时抛出错误。

4个回答

问题是前一个组件实例的侦听器仍然注册。因为之前的实例不再挂载,你会得到那个错误。

.bind总是返回一个函数。所以如果你这样做

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

那么您正在尝试删除一个不存在的侦听器(当然失败了)。它并不会删除您注册的监听器AppStore.listen(this.onChange.bind(this))


要解决这个问题,您应该在构造函数绑定一次处理程序

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

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

在更改之前,安装了状态检查组件。

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

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

我想这会对你有所帮助。

在您的情况下,向根 div 添加一个 ref 并在调用 setState 之前检查 ref 值。

您的onChange方法应如下所示:

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

我也在这个问题上挣扎了很长一段时间。

为我解决的是按照@Felix Kling 的建议进行操作,但还要确保在组件的类中声明了我的回调函数,否则您将无法使用this前缀,这显然对我有用

这是我的意思的一个例子:

合法,但不起作用

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() { ... }
}

作品

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() { ... }
}

希望它可以帮助其他人面临这个问题。:)