Деконструированное состояние не обновляется даже в обратном вызове setState

Возникла проблема, из-за которой деконструкция состояния компонента препятствует его обновлению в setState:

state = {
   value: 'test',
   values: ['a', 'b', 'c'],
};

...

const { value, values } = this.state;

this.setState(
  {
    values: [...values, value],
  },
  () => {
    console.log(values);
    // this logs ["a", "b", "c"] rather than ["a", "b", "c", "test"]
  }
);

Ожидаемый вывод значений должен включать новое значение, но при этом регистрируются только старые значения. Использование this.state работает, поэтому просто интересно, почему деконструкция объекта состояния не обновляется должным образом?

Вы можете перейти в эту Codesandbox и попробовать сами, нажав на кнопку и проверьте журналы консоли.

Любая помощь по этому поводу будет очень признательна!


person SnakeyHips    schedule 14.08.2019    source источник
comment
Он обновляется, но вы печатаете старое значение, а не новое. Итак, если вы дважды нажмете кнопку, вы увидите обновление.   -  person Colin Ricardo    schedule 14.08.2019
comment
Вы должны вести консольный журнал this.state.values. values ​​по-прежнему относятся к локальной переменной, которая относится к старому this.state.values   -  person Mukesh Soni    schedule 14.08.2019
comment
Прокомментировал предоставленный ответ, но да, спасибо за объяснение, ребята!   -  person SnakeyHips    schedule 14.08.2019


Ответы (2)


Предположим следующее:

state = {value: 0}
foo = () =>{
    const { value } = this.state
    this.setState({value : value + 1}, () => console.log(value)) //0
}

Это происходит потому, что value содержит значение состояния с момента вызова метода foo(), даже после обновления состояния значение этого const не изменится, потому что оно эквивалентно: const value = this.state.value. Это ссылка на то, чем раньше было это значение. В этом случае используйте глобальный экземпляр state, чтобы получить доступ к обновленному значению.

this.setState({value : value + 1}, () => console.log(this.state.value))//1
person Dupocas    schedule 14.08.2019
comment
Ах хорошо. Я предполагаю, что это не проблема, если делать это в функции render (), поскольку константа this.state переназначается при каждой отрисовке, поэтому работает там, но не вне отрисовки. Спасибо за объяснение! - person SnakeyHips; 14.08.2019
comment
Точно. Это нормально делать в рендере, потому что он вызывается каждый раз при изменении состояния, поэтому он всегда сохраняет текущее состояние. - person Dupocas; 14.08.2019

Может быть, вы могли бы попробовать что-то вроде этого:

state = {
   value: 'test',
   values: ['a', 'b', 'c'],
};

this.setState(oldState => 
  const { value, values } = oldState;
  return {
    values: [...values, value],
  },
  () => {
    console.log(values);
    // this logs ["a", "b", "c"] rather than ["a", "b", "c", "test"]
  }
);

В вашем примере вы пытаетесь распечатать старые значения состояния, те, которые только что произошли до setState. Итак, вы в основном устанавливаете значения такими, какими они были раньше. setState фактически также принимает функцию обратного вызова, из которой вы можете извлечь старое состояние. Там вы можете деструктурировать значения и т. Д., Попробуйте и удачи!

person aaa7c4    schedule 14.08.2019