Подтвердить что ты не робот

React setState может обновлять только смонтированный или монтажный компонент

Я получаю следующее предупреждение

"Предупреждение: 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;

Когда я помещаю отладчики, при загрузке контактной страницы он попадает в компонентWillMount(). Когда я покидаю страницу контакта, он попадает в компонентWillUnmount(). Когда я перейду на страницу назад, он снова попадает в состав компонента componentWillMount(), а затем выдает ошибку, когда она попадает в функцию onChange (состояние).

4b9b3361

Ответ 1

Проблема заключается в том, что слушатель предыдущего экземпляра компонента все еще зарегистрирован. И поскольку предыдущий экземпляр больше не монтируется, вы получаете эту ошибку.

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

Ответ 2

Перед изменением установлен компонент проверки состояния.

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

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

Я думаю, это поможет вам.

Ответ 3

В вашем случае добавьте ref в свой корневой раздел и проверьте значение ref перед вызовом setState.

Ваш метод onChange должен выглядеть следующим образом:

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