Состояние и setState() в React

Скорее всего, многие из вас уже использовали состояния React и знаете, что в случае смены состояния React запускает процесс повторного отображения компонента (конечно, если вы не укажете иное в shouldComponentUpdate()). Но как же изменить состояние? Об этом и поговорим.

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

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

Гладя на изображение выше, становится очевидным, что сначала мы вызываем setState(), а потом console.log(). При этом новое значение переменной counter должно равняться единице, однако выводится ноль. А что делать, если мы желаем получить доступ к новому состоянию после того, как setState() в действительности обновит свое состояние?

И вот здесь мы плавно подошли к очередному моменту, который надо знать о setState(). Заключается он в том, что данный метод способен принимать callback-функцию.

Давайте внесем исправления в код:

Казалось бы, всё работает, то есть на этом можно закончить. Но ничего подобного. На деле в этом случае мы не применяем setState() корректно. Вместо того, чтобы передавать объект, мы передаем методу функцию. Обычно, так делается, если для установки нового состояния применяется состояние текущее. Если же это не ваш случай, то можно продолжать передавать объект в setState(). Давайте исправим код ещё раз:

Вот для этого примера CodePen.

Какой же смысл в передаче функции вместо объекта?

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

Что касается передачи функции в setState(), то она предоставляет 2 преимущества: 1. Появляется возможность создавать статичную копию состояния, которое само по себе никогда не изменится. 2. Вызовы setState() будут помещены в очередь, в результате чего они станут запускаться по порядку.

Давайте рассмотрим следующий пример, где мы пытаемся увеличить счётчик на два, применяя 2 последовательных вызова setState():

Сравниваем с кодом ниже:

CodePen здесь. На первом изображении обе функции setState() используют this.state.counter напрямую, который останется со значением ноль после нашего первого вызова setState(). В результате конечное значение будет равно 1, а не 2, ведь обе функции setState() устанавливают, что значение счетчика равно единице.

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

Пожалуй, это все, что надо знать о состояниях в React.

Первоисточник