Spec-Zone.ru › Redux 3

Предыстория

Redux имеет смешанное происхождение. Оно сходно с некоторыми шаблонами и технологиями, но также отличается от них важными аспектами. Ниже мы рассмотрим некоторые сходства и различия.

Flux

Можно ли считать Redux реализацией Flux?
Да, и нет.

(Не беспокойтесь, создатели Flux одобряют его, если это всё, что вам хотелось узнать.)

Redux был вдохновлён несколькими важными качествами Flux. Как и Flux, Redux предписывает концентрировать логику обновления модели в определённом слое приложения («хранилища» в Flux, «редукторы» в Redux). Вместо того, чтобы позволять коду приложения напрямую изменять данные, оба подхода предлагают описывать каждое изменение как простой объект, называемый «действием».

В отличие от Flux, Redux не имеет понятия о Диспечере. Это потому, что он полагается на чистые функции вместо генераторов событий, а чистые функции легко комбинировать и не нуждаются в дополнительной сущности для их управления. В зависимости от того, как вы рассматриваете Flux, вы можете увидеть это как отклонение или деталь реализации. Flux часто описывается как (state, action) => state. В этом смысле Redux верен архитектуре Flux, но упрощает её благодаря чистым функциям.

Ещё одно важное отличие от Flux состоит в том, что Redux предполагает, что вы никогда не изменяете свои данные. Вы можете использовать обычные объекты и массивы для своего состояния, но изменение их внутри редукторов строго не рекомендуется. Вы всегда должны возвращать новый объект, что легко сделать с помощью предложения по оператору распространения объектов или с помощью библиотеки, такой как Immutable.

Хотя технически возможно создавать нечистые редукторы, которые изменяют данные для ситуаций с производительностью, мы настоятельно рекомендуем этого не делать. Функции разработки, такие как путешествие во времени, запись/воспроизведение или горячая перезагрузка, будут нарушены. Более того, в большинстве реальных приложений кажутся проблемы производительности, связанные с неизменяемостью, не критичными, поскольку, как демонстрирует Om, даже если вы теряете выделение объекта, вы все равно выигрываете, избегая дорогостоящих повторных рендерингов и перерасчётов, поскольку вы точно знаете, что изменилось благодаря чистоте редукторов.

Elm

Elm — функциональный язык программирования, вдохновлённый Haskell и созданный Evan Czaplicki. Он навязывает архитектуру «модель-представление-обновление», где обновление имеет следующий сигнатуру: (action, state) => state. Elm «обновлятели» выполняют ту же функцию, что и редукторы в Redux.

В отличие от Redux, Elm — это язык, поэтому он может извлечь выгоду из таких вещей, как принудительная чистота, статическая типизация, неизменяемость по умолчанию и сопоставление с образцом (используя case выражение). Даже если вы не планируете использовать Elm, вы должны ознакомиться с архитектурой Elm и поэкспериментировать с ней. Существует интересная платформа для экспериментов с JavaScript, реализующая похожие идеи. Мы должны черпать вдохновение оттуда для Redux! Один из способов приблизиться к статической типизации Elm — это использование решения постепенной типизации, такого как Flow.

Неизменяемость

Immutable — библиотека JavaScript, реализующая структуры данных с постоянством. Она производительна и имеет интуитивно понятный API JavaScript.

Immutable и большинство похожих библиотек ортогональны Redux. Не стесняйтесь использовать их вместе!

Redux не заботится о том, *как* вы храните состояние — это может быть обычный объект, объект Immutable или что-то ещё. Вероятно, вам потребуется механизм (де)сериализации для написания универсальных приложений и гидратации их состояния из сервера, но помимо этого вы можете использовать любую библиотеку хранения данных, *если она поддерживает неизменяемость*. Например, использовать Backbone для состояния Redux не имеет смысла, так как модели Backbone изменяемы.

Обратите внимание, что даже если ваша библиотека неизменяемости поддерживает курсоры, не следует использовать их в приложении Redux. Вся древовидная структура состояния должна рассматриваться как только для чтения, и вы должны использовать Redux для обновления состояния и подписки на обновления. Таким образом, запись через курсор не имеет смысла для Redux. Если единственный ваш случай использования курсоров — это отсоединение древовидной структуры состояния от древовидной структуры пользовательского интерфейса и постепенное уточнение курсоров, вы должны рассмотреть использование селекторов. Селекторы — это составные функции-получатели. См. reselect для отличной и лаконичной реализации составных селекторов.

Baobab

Baobab — ещё одна популярная библиотека, реализующая неизменяемый API для обновления обычных JavaScript-объектов. Вы можете использовать её с Redux, но в этом мало пользы.

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

В отличие от Immutable, Baobab ещё не реализует какие-либо специальные эффективные структуры данных под капотом, поэтому вы не получите каких-либо преимуществ от её совместного использования с Redux. В этом случае проще использовать обычные объекты.

RxJS

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

Имеет ли смысл использовать Redux вместе с RxJS? Конечно! Они отлично работают вместе. Например, легко преобразовать хранилище Redux в наблюдаемое:

function toObservable(store) {
  return {
    subscribe({ next }) {
      const unsubscribe = store.subscribe(() => next(store.getState()))
      next(store.getState())
      return { unsubscribe }
    }
  }
}

Аналогично, можно комбинировать различные асинхронные потоки, чтобы преобразовать их в действия перед подачей их в store.dispatch().

Вопрос в том: действительно ли вам нужен Redux, если вы уже используете Rx? Возможно, нет. Нетрудно перереализовать Redux в Rx. Некоторые говорят, что это всего лишь двухстрочная операция с использованием метода Rx .scan(). Возможно, так и есть!

Если вы сомневаетесь, ознакомьтесь с исходным кодом Redux (там нет ничего сложного), а также с его экосистемой (например, инструментами разработчика). Если вы не слишком на этом зациклены и хотите продолжать использовать реактивный поток данных, вы можете изучить что-то вроде Cycle, или даже объединить его с Redux. Дайте нам знать, как у вас пойдёт!

© 2015–2017 Dan Abramov
Licensed under the MIT License.
http://redux.js.org/docs/introduction/PriorArt.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API