Распространенный вопрос StackOverflow

Так часто я читаю несколько вариантов этого вопроса в StackOverflow, за которыми следует следующий код

const doSomethingWithTheState = () => {
  setState(newValue);
  console.log(state); // this prints the old value
};

И я всегда отвечаю одним и тем же отрывком из страницы документации React: setState () не всегда сразу обновляет компонент. Он может выполнить пакетное обновление или отложить его на потом. Это делает чтение this.state сразу после вызова setState () потенциальной ловушкой .

Почему React так справляется с этим?

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

Давайте еще раз проверим наш пример кода:

const doSomethingWithTheState = () => {
  setState(newValue);
  console.log(state); // this prints the old value
};

Если бы состояние было обновлено немедленно, это означало бы вызов алгоритма согласования при переходе к первой строке, которая вызовет повторную визуализацию, чтобы иметь возможность продолжить выполнение следующей строки, React должен будет сохранить контекст того, что выполнять. следующий будет дорого. Вот почему React решает этого не делать и сначала выполняет console.log.

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

Хотите решить эту проблему?

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

Если вы используете Компонент класса

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

doSomethingWithTheState = () => {
  this.setState(newValue, state => {
    console.log(state); // this prints the updated value
  })
};

После повторной визуализации все переменные состояния будут обновлены до самого последнего значения и будет вызвана функция componentDidUpdate, в этой функции у вас будет доступ к новому и предыдущему значениям.

componentDidUpdate(prevProps, prevState) {
  if (this.state !== prevState) {
    console.log(this.state); // this prints the updated value
  }
}

Если вы используете Функциональный компонент

Используйте ловушку useEffect, указав значение, которое вы хотите отслеживать в массиве зависимостей, как в следующем коде:

const [state, setState] = useState()
useEffect(() => {
  console.log(state); // this prints the updated value
}, [state]); // this will be triggered only when state value is different

Вывод

Теперь вы знаете наиболее частую причину, по которой ваше состояние не обновляется.

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