Когда я был на буткемпе, мы научились писать React с компонентами класса и контекстом для глобального состояния. Я никогда не знакомился с Redux или редьюсерами. Только когда я сделал свою первую игру, я почувствовал необходимость использовать более надежное управление состоянием.

Мне нравится хук useState, но есть некоторые преимущества в содержании состояния в одном объекте. С отдельными частями состояния все может выйти из синхронизации. В One Dimensional Chess, игре, в которой я впервые использовал хук useReducer, у меня была одна часть состояния, которая контролировала текущую доску, и одна часть, которая отслеживала текущую команду. Это было проблемой, потому что команда менялась, если пользователь успешно делал правильный ход для выбранной фигуры, но если ход был недействительным, команда не менялась.

В документации React говорится, что useReducer предпочтительнее useState «…когда у вас сложная логика состояния, включающая несколько подзначений или когда следующее состояние зависит от предыдущего». Это довольно низкая планка для использования хука useReducer вместо обычного состояния функционального компонента. На самом деле почти все глобальные состояния соответствуют одному из этих условий.

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

Когда я планировал этот проект, моя интуиция подсказала мне использовать редьюсер, и я отговорил себя от этого, сказав, что управление формой с помощью редьюсера — это излишество. Состояние кредитного калькулятора включало только три значения: три строки из контролируемой формы ввода и логическое значение.

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

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