Нажмите здесь, чтобы опубликовать эту статью в LinkedIn »

Redux - очень популярная библиотека управления состоянием, которая в основном используется вместе с React. Людям это нравится, потому что она предоставляет предсказуемую модель данных, вдохновленную Архитектурой Вяза ™. Однако в сообществе JS есть много людей, которым не нравится это и которые предпочитают выбирать альтернативы, такие как MobX.

Подытожим основные плюсы и минусы, которые обычно возникают:

Сильные стороны Redux

  • Предсказуемость и простота
  • Однонаправленный поток данных и неизменность
  • Разделение данных и представления
  • Расширяемость (через промежуточное ПО)
  • Популярность и сообщество
  • Инструментальная поддержка

Слабые стороны Redux

  • Шаблон (представления, типы действий, создатели действий, редукторы, селекторы и т. Д.)
  • Нет готового решения для борьбы с побочными эффектами (доступно через промежуточное ПО, такое как redux-thunk или redux-saga).
  • Действия не связаны с их эффектом (который определяется в редукторе)

Подобный, но другой подход

В недавнем проекте, над которым я работал, я подумал: «Нужна ли мне вообще какая-то сторонняя библиотека для управления моим состоянием»? React - отличная библиотека сама по себе, и я могу контролировать свое состояние, имея неизменное значение с чистыми функциями для перехода между состояниями. Об остальном позаботится React.

Чистота

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

Чистый взгляд - это просто. React дает нам модель программирования

view = f(state)

Итак, все, что нам нужно сделать, это написать f. Нет необходимости в подключенных компонентах или состоянии внутреннего компонента. Мы также можем извлечь выгоду из чистых компонентов React, которые обеспечивают лучшую производительность по сравнению с обычными компонентами.

Чистое состояние - опять же, здесь нет необходимости в Redux. Мы можем просто использовать одно неизменяемое значение для представления всего состояния нашего приложения. Такие библиотеки, как Immutable.js или Ramda могут помочь нам в управлении неизменяемым состоянием.

Чистые обновления. И в Redux, и в Elm одной из ключевых частей вашего приложения является функция перехода между состояниями. В Elm это функция update, а в Redux - это reducer. Они оба имеют одинаковую структуру

(state, action) => new state

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

Действия

Как и в случае с Redux, я написал «создателей действий». Но в отличие от Redux, действия являются всего лишь контейнерами для функции обновления.

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

Беговые (побочные) эффекты

Нам нужна возможность вызывать побочные эффекты (например, отправку запросов AJAX) контролируемым и предсказуемым образом. В Elm это достигается путем разрешения функции update возвращать команду вместе с обновленной моделью. Сама команда не вызывает побочного эффекта, а просто описывает эффект, который должен иметь место. Мы будем использовать аналогичный подход, позволяя нашим действиям определять функцию runEffect. Это сохранит чистоту самих действий, поскольку на самом деле они не запускают эффекты. Это будет происходить вне нашей программы, в одном месте на краю света.

Мы обновим нашу функцию отправки, чтобы разрешить такое поведение:

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

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

  • Инструменты: поскольку здесь нет библиотеки и поддержки сообщества - нет таких замечательных инструментов, как Redux DevTools. Однако я обнаружил, что довольно легко добавить служебную функцию для отладки, которая регистрирует каждое действие со старым и новым состоянием.
  • Сериализуемость: действия Redux содержат только данные и тип действия. Это позволяет легко сохранять их или передавать по проводам. Это невозможно с создателями действий, которые я описал. Однако тех же преимуществ можно легко получить, добавив свойство type к объекту действия и имея некую фабричную функцию, которая может воссоздать объект действия из его полезных данных.

Заключение

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

Вот обязательная реализация todo MVC с использованием этого подхода: