React setState не обновляется немедленно

Я работаю над приложением todo. Это очень упрощенная версия оскорбительного кода. У меня есть флажок:

 <p><input type="checkbox"  name="area" checked={this.state.Pencil}   onChange={this.checkPencil}/> Writing Item </p>

вот функция, которая вызывает флажка:

checkPencil(){
   this.setState({
      pencil:!this.state.pencil,
  }); 
  this.props.updateItem(this.state);
}

updateItem-это функция, которая отображается для отправки в redux

function mapDispatchToProps(dispatch){
  return bindActionCreators({ updateItem}, dispatch);
}

моя проблема в том, что когда я вызываю действие updateItem и консоль.регистрируйте состояние, оно всегда на 1 шаг позади. Если флажок снят и не true, я все равно получаю состояние true передается функции updateItem. Нужно ли вызывать другую функцию, чтобы заставить состояние обновляться?

8 ответов


вы должны вызвать свою вторую функцию в качестве обратного вызова setState, так как setState происходит асинхронно. Что-то вроде:

this.setState({pencil:!this.state.pencil}, myFunction)

однако в вашем случае, так как вы хотите, чтобы эта функция вызывалась с параметром, вам придется немного более творчески и, возможно, создать свою собственную функцию, которая вызывает функцию в реквизите:

myFunction = () => {
  this.props.updateItem(this.state)
}

объедините их вместе, и это должно сработать.


вызов setState() in React является асинхронным по различным причинам (в основном производительность). Под обложками React будет пакетировать несколько вызовов setState() в одну мутацию состояния, а затем повторно визуализировать компонент один раз, а не повторно визуализировать для каждого изменения состояния.

к счастью, решение довольно простое - setState принимает параметр обратного вызова:

checkPencil(){
   this.setState({
      pencil:!this.state.pencil,
  }, function () {
      this.props.updateItem(this.state);
  }.bind(this));
}

когда вы обновляете свое состояние, используя свойство текущего состояния, документация React советует вам использовать версию вызова функции setState вместо объекта.

так setState((state, props) => {...}) вместо setState(object).

причина в том, что setState - это скорее запрос на изменение состояния, а не немедленное изменение. Реагируйте партиями те setState призывы к повышению производительности.

означает, что государственное свойство, которое вы проверяете, может не быть стабильный. Это потенциальная ловушка, о которой нужно знать.

для получения дополнительной информации см. документацию здесь:https://facebook.github.io/react/docs/react-component.html#setstate


чтобы ответить на ваш вопрос, я бы сделал это.

checkPencil(){
    this.setState((prevState) => {
        return {
            pencil: !prevState.pencil
        };
    }, () => {
        this.props.updateItem(this.state)
    });
}

потому что асинхронно, так что означает, что в это время может не обновляться еще...

согласно документации React v. 16, вам нужно использовать вторую форму setState() который принимает функцию, а не объект:

Обновления Состояния Могут Быть Асинхронными

React может пакетировать несколько вызовов setState() в одно обновление для спектакль.

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

например, этот код может не обновить счетчик:

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

чтобы исправить это, используйте вторую форму setState (), которая принимает функцию а не объект. Эта функция получит предыдущее состояние в качестве первого аргумента и реквизита во время применения обновления в качестве второго аргумента:

// Correct
this.setState((prevState, props) => ({
  counter: prevState.counter + props.increment
}));

я использовал оба предложения rossipedia и Ben Hare и сделал следующее:

checkPencil(){
   this.setState({
      pencil:!this.state.pencil,
   }, this.updatingItem); 
}

updatingItem(){
    this.props.updateItem(this.state)
}

У Бена есть отличный ответ на то, как решить непосредственную проблему, однако я бы также посоветовал избегать дублирования состояния

Если состояние находится в redux, ваш флажок должен считывать свое собственное состояние из prop или store вместо отслеживания состояния проверки как в своем собственном компоненте, так и в глобальном магазине

сделать что-то вроде этого:

<p>
    <input
        type="checkbox"
        name="area" checked={this.props.isChecked}
        onChange={this.props.onChange}
    />
    Writing Item
</p>

общее правило состоит в том, что если вы найдете состояние, необходимое в нескольких местах, поднимите его до общего родитель (не всегда redux), чтобы поддерживать только один источник истины


попробуй такое

this.setState({inputvalue: e.target.value}, function () {
    console.log(this.state.inputvalue);
    this.showInputError(inputs[0].name);
}); 

функция showInputError для проверки при использовании любых форм


установить значение. после приступайте к своим работам.

this.setState({inputvalue: e.target.value}, function () {
    this._handleSubmit();
}); 

_handleSubmit() {
   console.log(this.state.inputvalue);
   //Do your action
}