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
}