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

Например:
Эти чистые функции принимают два значения, выполняют операцию и возвращают результат.

function (a, b) { return a + b; }
function (a, b) { return a / b; }
function (a, b) { return (a + b)/2; }

Просто, а?

Теперь, когда мы понимаем, что такое базовый редьюсер, давайте расширим эту идею.

В качестве примера рассмотрим addReducer, который принимает значение state и добавляет к нему значение change, эффективно объединяя оба значения в новый объект состояния. . Это иллюстрирует, как работают редукторы и обновляют состояние нашего приложения.

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

В приведенном ниже примере мы видим, как редьюсер выполняется три раза, при этом результат каждого выполнения передается как состояние, а значение состояния увеличивается при каждом выполнении.

После 3 сокращений значение состояния увеличивается с 5 до 15.

вывод консоли:
результат уменьшения суммы: 15

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

Давайте представим другой тип редуктора, который работает по-другому — removeReducer. Эта функция вычитает значение из состояния, создавая новый объект состояния. Это демонстрирует гибкость и универсальность редукторов в манипулирующем состоянии.

вывод консоли:
состояние после 3 применений addReducer: 15
состояние после 3 применений removeReducer: 6

Надеюсь, вы уловили концепции, которые мы рассмотрели до сих пор. Мы рассмотрели два редюсера: addReducer и removeReducer, оба из которых применяют изменения к состоянию. addReducer увеличивает значение состояния, а removeReducer уменьшает его.

Одним из существенных преимуществ использования редюсеров является то, что они дают четкое представление о том, как они повлияют на состояние. Применяя изменения через редюсеры, мы можем быть уверены, что состояние будет обновляться последовательно и предсказуемо, что упростит тестирование и отладку.

Однако когда мы выходим за рамки индивидуального выполнения редюсеров и вместо этого применяем массивы изменений значений, ситуация становится более интригующей. К счастью, родной метод Array reduce() может помочь в этом процессе. Давайте посмотрим, как мы можем использовать его, чтобы переписать наш предыдущий пример.

вывод консоли:
состояние после 3 применений addReducer: 15
состояние после 3 применений removeReducer: 6

Используя метод Array.reduce(), теперь мы можем применять редукторы к последовательности изменений, что приводит к тому же результату, что и раньше. Этот обновленный подход позволяет нам более организованно и эффективно манипулировать нашим состоянием, что делает его ценным инструментом для разработчиков.

На данном этапе механизм редуктора является относительно простым. Хотя мы можем изменить состояние с помощью редюсера, мы можем сделать это только в последовательности последовательных изменений, что делает процесс несколько ограниченным.

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

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

  • Преобразование значений изменений в объекты, описывающие изменение (действия).
  • Централизация логики редуктора в одном месте

вывод консоли:
состояние после выполнения всех действий: 6

Крайне важно понимать, что массив изменений теперь содержит последовательность объектов, описывающих действие, выполняемое в редюсере. Это значительное улучшение, поскольку оно отделяет события приложения от непосредственного выполнения редюсеров.

Одно из преимуществ использования объектов действия с редьюсерами заключается в том, что редьюсер может деконструировать объект действия на отдельные переменные типа и изменения. Поступая таким образом, редьюсер может определить, какое сокращение следует применить к объекту состояния.

Это отделяет события приложения от непосредственного выполнения редюсеров, обеспечивая более гибкий и надежный подход к проектированию.

Существует несколько способов дальнейшего улучшения конструкции для улучшения механизма редуктора.

  • мы могли бы отказаться от использования объектной нотации для действий и вместо этого ввести более простой способ создания действий с помощью класса Action.
  • мы могли бы реализовать функции создателя действий, которые генерируют объект Action из своих параметров функции.
  • мы могли бы ввести функцию addChange для немедленного добавления объекта Action в массив изменений, обеспечивая еще большую гибкость и контроль над механизмом редьюсера.

вывод консоли:
состояние после выполнения всех действий: 6

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

Основная идея проста: для обработки асинхронных событий в нашем приложении мы генерируем объекты действий с помощью генераторов действий. Затем эти объекты действий добавляются в очередь изменений, которые обрабатывает редюсер. Этот подход позволяет нам отделить события приложения от прямого выполнения редюсеров, обеспечивая более гибкую и масштабируемую архитектуру.

Проверьте мой фреймворк с открытым исходным кодом QQ:

https://github.com/jsmuster/qq

Посмотрите другие мои статьи







Автономное использование Redux
В своей предыдущей статье «Понимание редукторов с нуля
я представил редюсеры как концепцию и расширил ее до…medium.com»





Пожалуйста, дайте статье немного 👏 и поделитесь ею!

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Присоединяйтесь к нашему сообществу Discord и следите за нами в Twitter, LinkedIn и YouTube.

Узнайте, как привлечь внимание к своему стартапу с помощью Circuit.