Иногда для того, чтобы научиться делать, нужно научиться тому, чего не следует делать.
Эта статья также доступна в видеоформате.
Примеры из этой статьи доступны для скачивания.
Во-первых, я должен поблагодарить автора Как НЕ реагировать: общие антипаттерны и ошибки в React за вдохновение для этой статьи.
Анти-шаблон
Во-первых, мне неловко узнать, что я долгое время делал что-то не так (в значительной степени с тех пор, как я начал использовать React где-то в 2014 году). Я всегда считал функцию setState синхронной с простой подписью:
setState(nextState)
Фактически, если вы вернулись к документации еще в середине 2015 года и быстро прочитали ссылку, вы придете к такому же выводу. Если бы вы читали дальше, то узнали бы иначе.
примечание: в свое оправдание я также быстро переключился на использование Redux для управления состоянием и поэтому редко (если вообще когда-либо) использовал setState прямо.
Ниже приведен пример компонента с увеличивающимся счетчиком, который я много раз использовал на тренировках; но на этот раз я добавлю тонкий (несколько надуманный) поворот. В этом случае нажатие кнопки Increment дважды вызывает setState.
Код:
примечание: в моем обучающем примере функция increment - это обработчик onClick (один вызов setState на клик) . В этом случае, из-за времени, я никогда не видел проблемы.
Так что же происходит, когда вы нажимаете кнопку Приращение?
Счетчик изменился с 0 на 1.
Если вы считаете, что setState является синхронным (как и я), то вы ожидали, что значение будет равно 2. Каждый вызов setState синхронно изменяет состояние компонента и повторно отображает его.
Очевидно, я ошибался.
Лучший способ
Во-первых, если мы сейчас посмотрим на ссылку для setState, вы даже не увидите сигнатуры setState, к которой я (и многие другие) привык; т.е. непосредственно установка следующего состояния.
Позже он демонстрирует более знакомую (по крайней мере, для меня) сигнатуру, а затем сразу же иллюстрирует антипаттерн, который мы здесь исследуем.
В исправленном коде используется правильная подпись для setState; передача функции обновления increment.
примечание: если вы писали с помощью Redux, этот шаблон аналогичен функциям редуктора, которые вы используете.
В этом коде нажатие кнопки Приращение ведет себя должным образом:
Когда использовать более простую форму
Узнав об этом анти-шаблоне, я подумал, есть ли ситуация, когда безопасно использовать более простую форму setState?
setState(nextState)
Ответ - да, но только если следующее состояние не зависит ни от текущего состояния, ни от свойств.
Дальнейшие действия
Если вы нашли эту статью полезной, я бы посоветовал вам подписаться на меня, так как я активно пишу больше в том же духе.