Реагировать 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 - это функция, отображаемая для отправки в приставку

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

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

 zerkms25 июл. 2016 г., 02:37
Вы не звоните другомуsetState. setState принимает второй аргумент, который является обратным вызовомfacebook.github.io/react/docs/component-api.html#setstate
 lost912319325 июл. 2016 г., 02:36
@zerkms Я думаю, я понимаю, что вы имеете в виду, но не могли бы вы уточнить, как бы я назвал другое setState в контексте флажка?
 zerkms25 июл. 2016 г., 02:29
Повторный рендеринг асинхронен сsetState, Вы можете использовать второйsetState Аргумент, который вызывается после повторной визуализации компонента. PS: выглядит подозрительно, что вам нужно передать полное состояние компонента вверх.

Ответы на вопрос(8)

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

updatingItem(){
    this.props.updateItem(this.state)
}
 Parvindra Singh09 мар. 2019 г., 17:16
Я получил ошибку this.props.updateItem не является функцией. Я не понимаю, почему эта ошибка происходит в моем случае.
 Ben Hare25 июл. 2016 г., 03:32
И это сработало?
 lost912319325 июл. 2016 г., 03:36
Да, это сработало!
Решение Вопроса

ate, так как setState происходит асинхронно. Что-то вроде:

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

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

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

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

 rossipedia27 окт. 2017 г., 18:09
В функциях стрелок,this привязан к объему, так что я уверен, что у вас это задом наперед.
 J.Ko14 дек. 2018 г., 18:55
Решение не достаточно описательное.

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

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

Обновления состояния могут быть асинхронными

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

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

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

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

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

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

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

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

Сделайте что-то вроде этого:

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

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

используя свойство текущего состояния, в документации 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)
    });
}
 chii11 авг. 2017 г., 04:10
Спасибо. это сработало для меня.

попробуй это

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
}
 rollstuhlfahrer23 февр. 2018 г., 12:47
Хотя этот код может ответить на вопрос, предоставление дополнительного контекста относительно того, почему и / или как этот код отвечает на вопрос, повышает его долгосрочную ценность.

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

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

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

Ваш ответ на вопрос