Flux на пальцах
Last updated
Last updated
Компоненты не содержат бизнес-логику, а отвечают лишь за рендеринг интерфейса.
В приложении существует один объект, который хранит состояние всего приложения. Я буду называть его "глобальным состоянием", хотя не совсем уверен, что это наиболее удачный термин. Некоторые компоненты по желанию разработчика "подписываются" на интересующую их часть глобального состояния. С течением времени глобальное состояние может изменяться, а все подписанные на него компоненты получают обновления автоматически.
Запрещено явно изменять глобальное состояние внутри компонента. Для изменения глобального состояния компоненты вызывают специальную функцию dispatch
. Отслеживание хода выполнения этой функции является anti-pattern, так как нарушает первый принцип Flux. На практике глобальное состояние будет содержать всю необходимую вашему компоненту информацию, например, статус выполнения API запроса и ошибки. Эта и другая информация будет своевременно и явно передаваться вашему компоненту с помощью props.
Важное примечание: глобальное состояние описывает лишь состояние вашего front-end приложения в отдельной вкладке и хранится исключительно в оперативной памяти браузера. Таким образом, оно будет утеряно, если пользователь нажмет F5, что абсолютно нормально, ожидаемо и by design.
Допустим, у нас есть сайт интернет-магазина: в центре страницы мы увидим список товаров, в панели навигации — иконку корзины с количеством товаров и общей их стоимостью, а где-то справа — блок с детализацией товаров, добавленных в корзину. Одним словом, достаточно распространенный сценарий.
Пользователь нажимает на кнопку "Добавить в корзину".
Кнопка перестает быть активной, ее иконка изменяется на индикатор загрузки.
Выполняется запрос серверного API.
После того, как серверная часть успешно обработала запрос и вернула ответ, сверху появляется подсказка "Товар был успешно добавлен в корзину", значение иконки с количеством товаров увеличивается на один, сумма пересчитывается, в блоке с детализацией содержимого корзины появляется новая запись. Индикатор загрузки исчезает, а сама кнопка снова становится активной.
В случае ошибки на 3 шаге, показываем пользователю сообщение с ошибкой и возвращаем кнопку добавления товара в корзину в первоначальное состояние.
Если бы мы писали этот сценарий на jQuery, то пришлось бы написать много кода для работы с DOM'ом. В процессе реализации все новых требований заказчика код становился бы все запутаннее, и, с большой долей вероятности, что-нибудь в итоге сломалось бы, а сложность и стоимость поддержки постоянно увеличивалась бы с течением времени и новых "хотелок".
Примечание: компоненты "Добавить в корзину", "Уведомления", "Корзина" и "Детализация Корзины" подписаны на глобальное состояние.
Пользователь нажимает на кнопку "Добавить в корзину", что приводит к вызову функции dispatch
.
Эта функция обновляет глобальное состояние: кнопка "Добавить в корзину" получает новое значение prop loading
равное true, что делает ее выключенной, а ее иконка меняется на индикатор загрузки согласно исходному коду этого компонента.
Следующим шагом функция делает запрос к API, чтобы сохранить в бэкенде информацию о добавленном товаре.
В случае успеха обновим глобальное состояние: компонент "Уведомления" получит новое значение prop message
, что сделает его видимым для пользователя, компонент "Корзина" получит значения prop count
с новым количеством товаров и prop value
с суммой заказа, компонент "Детализация корзины" получит значение prop items
— обновленный список объектов, соответствующих всем товарам, добавленным в корзину. Если в будущем заказчик пожелает, чтобы на странице происходило что-то еще, мы легко сможем воплотить это в жизнь, не меняя ни код других компонентов, ни функцию, которая выполняет бизнес-логику. Нам достаточно лишь реализовать новый компонент и в нем же указать, какая часть глобального состояния нас интересует.
Если API вернул ошибку, то компонент "Уведомления" получит соответствующее значение prop message
и покажет пользователю информационное сообщение.
Функция в последний раз обновит глобальное состояние, сообщив кнопке "Добавить в корзину" новое значение prop loading
равное false. Кнопка снова вернется в свое первоначальное состояние.