Как использовать setState () в React, чтобы очистить / очистить значение массива

Я пытаюсь очистить массив, но возникают проблемы. this.setState({warnErrorTypes:[]})

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

Как заменить массив, содержащий [1,2], на [], а затем [3], если верно следующее:

  1. this.state.warnErrorTypes - это массив, который начинается с []
  2. В зависимости от условия, 2 помещается в массив
  3. В зависимости от условия в массив помещается 1.
  4. Исходя из условия, 3 НЕ помещается в массив
  5. Пауза. Пользователь взаимодействует с пользовательским интерфейсом
  6. Массив не заполнен: this.setState({warnErrorTypes:[]})
  7. В зависимости от условия, 2 НЕ помещается в массив
  8. В зависимости от условия 1 НЕ помещается в массив
  9. В зависимости от условия в массив помещается 3.

Результатом приведенной выше логики всегда будет [2,1,3], когда я ожидаю, что это будет [3].


person JZ.    schedule 01.05.2015    source источник
comment
Не могли бы вы привести пример, показывающий проблему в JSBin / jsfiddle?   -  person Anders Ekdahl    schedule 01.05.2015
comment
gist.github.com/fogonthedowns/d7a1ddb28129c82fad0c   -  person JZ.    schedule 01.05.2015


Ответы (3)


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

Опция 1:

moo: function() {
  this.setState({
    myarr: []
  }, function() { // called by React after the state is updated
    this.setState({
      myarr: [3]
    });
  });
}

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

Вариант 2:

getInitialState: function() {
  this.mylist = [];
  return {
    myarr: this.mylist
  };
},
...
moo: function() {
  this.mylist = [];
  for(var i=0; i<10; i++) {
    this.mylist.push(i);
  }
  this.setState({ myarr: this.mylist });
}

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

Вариант 3:

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

moo: function() {
  var list = this.state.myarr;
  while(list.length > 0) { list.splice(0,1); }
  for(var i=0; i<10; i++) { list.push(i); }
  this.setState({ myarr: list });
}

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

person Mike 'Pomax' Kamermans    schedule 01.05.2015
comment
Также можно передать функцию setState, которая получает текущее состояние ожидания в качестве аргумента и должна возвращать новое состояние. Это позволяет легко избежать многократных вызовов setState сбивания значений друг друга. - person Anders Ekdahl; 02.05.2015
comment
'' вызывается React после обновления состояния: p Спасибо! - person Aimal Khan; 25.10.2018

Вариант 3, как сказал Андерс Экдал:

  moo () {
    this.setState(state => ({
      myarr: []
    }));

    // ...

    if (weShouldAddAThree) {
      this.setState(state => ({
        myarr: [ ...state.myarr, 3 ]   // like push but without mutation
      }));
    }
  }

Этот шаблон полезен, если вам нужно обратиться к предыдущему существующему состоянию при выполнении обновления состояния. Я не уверен, действительно ли вам нужно предыдущее состояние в вашем примере, но я объясню этот шаблон, как если бы вы это сделали.

Операция слияния, которую мы предоставляем для setState, всегда применяется асинхронно, в какой-то момент в будущем на усмотрение React. Когда функция setState() возвращается, наша операция не была применена, она только была поставлена ​​в очередь.

Поэтому мы никогда не должны использовать this.state в нашем средстве обновления состояния, потому что оно может быть устаревшим: старая копия состояния. Если нам нужно знать предыдущее состояние, мы должны получить аргумент state в функции, которую мы передаем в setState, и использовать его.

person joeytwiddle    schedule 05.02.2018

Вы также можете использовать это для очистки массива без использования setState:

   this.state.your_array.length = 0;
person leeCoder    schedule 06.06.2019