Зачем использовать Redux над Facebook Flux?

Я прочитал этот ответ, сокращая шаблон, посмотрел несколько примеров GitHub и даже немного попробовал редукс (приложения todo).

Как я понимаю, официальные мотивы приведения к редуксу дают плюсы по сравнению с традиционными архитектурами MVC. НО это не дает ответа на вопрос:

Почему вы должны использовать Redux поверх Facebook Flux?

Это только вопрос стилей программирования: функциональный против нефункционального? Или вопрос в способностях/инструментах разработки, которые следуют из подхода редукса? Может масштабирование? Или тестирование?

Прав ли я, если скажу, что редукс - это поток для людей, которые приходят с функциональных языков?

Чтобы ответить на этот вопрос, вы можете сравнить сложность реализации мотивации редукса в потоке против редукса.

Вот побудительные мотивы от официальных побудительных мотивов:

  1. Обработка оптимистичных обновлений (насколько я понимаю, это вряд ли зависит от 5-го пункта. Сложно ли реализовать это в Facebook Flux?)
  2. Рендеринг на сервере (Facebook Flux также может сделать это. Есть ли преимущества по сравнению с Redx?)
  3. Извлечение данных перед выполнением переходов по маршруту (Почему это невозможно сделать в Facebook Flux? Какие преимущества?)
  4. Горячая перезагрузка (это возможно с React Hot Reload. Зачем нам нужен редукс?)
  5. Отменить/Повторить функциональность
  6. Любые другие точки? Как постоянное состояние...

Ответ 1

Автор Redux здесь!

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

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

Состав редуктора

Взять, к примеру, нумерацию страниц. Мой пример Flux + React Router обрабатывает нумерацию страниц, но код для этого ужасен. Одна из причин, почему это ужасно, заключается в том, что Flux делает неестественным повторное использование функциональности в разных магазинах. Если двум хранилищам нужно обрабатывать нумерацию страниц в ответ на разные действия, им нужно либо наследовать от общего базового хранилища (плохо! Вы привязываетесь к конкретному дизайну, когда используете наследование), либо вызывать внешне определенную функцию изнутри обработчик событий, который должен каким-то образом работать в приватном состоянии хранилища Flux. Все это грязно (хотя определенно в области возможного).

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

Этот шаблон также позволяет использовать замечательные функции, такие как отмена/повтор выполнения без кода пользователя. Можете ли вы представить, что подключение Undo/Redo к приложению Flux представляет собой две строки кода? Едва. С Redux это - снова, благодаря шаблону композиции редуктора. Мне нужно подчеркнуть, что в этом нет ничего нового - это образец, впервые описанный и подробно описанный в Elm Architecture, который сам был под влиянием Flux.

Рендеринг сервера

Люди хорошо выполняли рендеринг на сервере с помощью Flux, но, увидев, что у нас есть 20 библиотек Flux, каждая из которых пытается сделать рендеринг сервера "более простым", возможно, у Flux есть некоторые острые углы на сервере. Правда в том, что Facebook не сильно рендерит сервер, поэтому их это не очень беспокоит, и они делают упор на экосистему.

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

В Flux по-прежнему есть следующие проблемы, которые вам нужно решить (самостоятельно или с помощью вашей любимой библиотеки Flux, такой как Flummox или Alt):

  • Если магазины являются классами, как мне создавать и уничтожать их диспетчером по запросу? Когда я регистрирую магазины?
  • Как мне гидрировать данные из магазинов, а затем повторно скопировать их на клиенте? Нужно ли реализовывать специальные методы для этого?

Конечно, фреймворки Flux (а не vanilla Flux) имеют решение этих проблем, но я считаю, что они слишком сложны. Например, Flummox просит вас реализовать serialize() и deserialize() в ваших магазинах. Alt решает эту проблему, предоставляя takeSnapshot() который автоматически сериализует ваше состояние в дереве JSON.

Redux идет еще дальше: поскольку существует только один магазин (управляемый многими редукторами), вам не нужен специальный API для управления (ре) гидратацией. Вам не нужно "очищать" или "увлажнять" магазины - там только один магазин, и вы можете прочитать его текущее состояние или создать новый магазин с новым состоянием. Каждый запрос получает отдельный экземпляр магазина. Узнайте больше о рендеринге сервера с помощью Redux.

Опять же, это случай чего-то возможного как в Flux, так и в Redux, но библиотеки Flux решают эту проблему, вводя тонну API и соглашений, и Redux даже не нужно ее решать, потому что у нее нет такой проблемы в Первое место благодаря концептуальной простоте.

Опыт разработчика

На самом деле я не собирался делать Redux популярной библиотекой Flux - я написал ее, когда работал над докладом ReactEurope о горячей перезагрузке с путешествиями во времени. У меня была одна главная цель: сделать возможным изменение кода редуктора на лету или даже "изменить прошлое", перечеркнув действия, и увидеть, как состояние пересчитывается.

Я не видел ни одной библиотеки Flux, которая могла бы сделать это. React Hot Loader также не позволяет вам этого делать - на самом деле он ломается, если вы редактируете хранилища Flux, потому что он не знает, что с ними делать.

Когда Redux требуется перезагрузить код редуктора, он вызывает replaceReducer(), и приложение запускается с новым кодом. В Flux данные и функции запутаны в хранилищах Flux, поэтому вы не можете "просто заменить функции". Более того, вам придется как-то перерегистрировать новые версии с помощью Dispatcher - чего у Redux даже нет.

экосистема

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

Простота

Redux сохраняет все преимущества Flux (запись и воспроизведение действий, однонаправленный поток данных, зависимые мутации) и добавляет новые преимущества (простая отмена, горячая перезагрузка) без использования Dispatcher и регистрации магазина.

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

В отличие от большинства библиотек Flux, поверхность Redux API крошечная. Если вы удалите предупреждения разработчика, комментарии и проверки работоспособности, это будет 99 строк. Нет сложного асинхронного кода для отладки.

Вы действительно можете прочитать его и понять все о Redux.


Смотрите также мой ответ о минусах использования Redux по сравнению с Flux.

Ответ 2

В Quora кто-то говорит :

Прежде всего, полностью возможно написать приложения с React без Flux.

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

Но если вам все еще интересно узнать больше, читайте дальше.

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

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

Если вы начнете непосредственно с Redux, вы можете столкнуться с чрезмерно сложным кодом, который сложнее поддерживать, и с еще большим количеством ошибок, чем без Redux.

Из документов Redux:

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

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

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

С этой сложностью трудно справиться, поскольку мы смешиваем две концепции, которые человеческому разуму очень трудно рассуждать: мутация и асинхронность. Я называю их Ментос и Кола. Оба могут быть хороши, когда разделены, но вместе они создают беспорядок. Такие библиотеки, как React, пытаются решить эту проблему на уровне представления путем устранения как асинхронности, так и прямой манипуляции с DOM. Однако управление состоянием ваших данных остается за вами. Здесь Redux приходит.

Следуя по стопам Flux, CQRS и Event Sourcing, Redux пытается сделать изменения состояния предсказуемыми, накладывая определенные ограничения на то, как и когда могут происходить обновления. Эти ограничения отражены в трех принципах Redux.

Также из документов Redux:

Основные понятия
Сам Redux очень прост.

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

{
  todos: [{
    text: 'Eat food',
    completed: true
  }, {
    text: 'Exercise',
    completed: false
  }],
  visibilityFilter: 'SHOW_COMPLETED'
}

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

Чтобы изменить что-то в состоянии, вам нужно отправить действие. Действие - это простой объект JavaScript (обратите внимание, как мы не представляем никакой магии?), Который описывает, что произошло. Вот несколько примеров действий:

{ type: 'ADD_TODO', text: 'Go to swimming pool' }
{ type: 'TOGGLE_TODO', index: 1 }
{ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }

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

function visibilityFilter(state = 'SHOW_ALL', action) {
  if (action.type === 'SET_VISIBILITY_FILTER') {
    return action.filter;
  } else {
    return state;
  }
}

function todos(state = [], action) {
  switch (action.type) {
  case 'ADD_TODO':
    return state.concat([{ text: action.text, completed: false }]);
  case 'TOGGLE_TODO':
    return state.map((todo, index) =>
      action.index === index ?
        { text: todo.text, completed: !todo.completed } :
        todo
   )
  default:
    return state;
  }
}

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

function todoApp(state = {}, action) {
  return {
    todos: todos(state.todos, action),
    visibilityFilter: visibilityFilter(state.visibilityFilter, action)
  };
}

Это в основном вся идея Redux. Обратите внимание, что мы не использовали API Redux. Он поставляется с несколькими утилитами для упрощения этого шаблона, но основная идея заключается в том, что вы описываете, как ваше состояние обновляется с течением времени в ответ на объекты действий, и 90% кода, который вы пишете, - это простой JavaScript, без использования Redux. сам по себе, его API, или любая магия.

Ответ 3

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

Во-вторых, на странице с мотивациями, на которую вы ссылаетесь, на самом деле не столько обсуждаются мотивы Redux, сколько мотивы, стоящие за Flux (и React). Три принципа более специфичны для Redux, но все же не имеют отношения к отличиям реализации от стандартной архитектуры Flux.

По сути, Flux имеет несколько хранилищ, которые вычисляют изменение состояния в ответ на взаимодействия пользовательского интерфейса /API с компонентами и транслируют эти изменения как события, на которые могут подписаться компоненты. В Redux есть только один магазин, на который подписывается каждый компонент. IMO, по крайней мере, кажется, что Redux еще больше упрощает и унифицирует поток данных, объединяя (или сокращая, как сказал бы Redux) поток данных обратно к компонентам - тогда как Flux концентрируется на объединении другой стороны потока данных - модель.

Ответ 4

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

Поскольку я немного опаздываю на разговор, я просто укажу, что, несмотря на мои лучшие надежды, Facebook, похоже, считает, что их реализация Flux является доказательством концепции, и она никогда не получала внимания, которого она заслуживает.

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

Мы решили, что двигаемся вперед, мы перейдем к Redux, и я предлагаю вам сделать то же самое;)

Ответ 5

Вот простое объяснение Redux над Flux. Redux не имеет диспетчера. Он опирается на чистые функции, называемые редукторами. Для этого не нужен диспетчер. Каждое действие обрабатывается одним или несколькими редукторами для обновления одного хранилища. Поскольку данные неизменны, редукторы возвращают новое обновленное состояние, которое обновляет хранилище enter image description here

Для получения дополнительной информации Flux против Redux

Ответ 6

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

Ответ 7

От нового усыновителя реагирования/избыточности, переходящего с (несколько лет) ExtJS в середине 2018 года:

Спустившись вниз по кривой изучения редукса, у меня возник тот же вопрос, и я подумал, что чистый поток будет проще, чем OP.

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

Получая контроль над плитой котла снова, я попробовал несколько других библиотек управления состоянием, лучшее, что я нашел, это реванш.

Он был гораздо более интуитивным, чем ванильный редукс, он отсекал 90% от стандартного и сокращал 75% времени, которое я тратил на редукс (что, я думаю, должна делать библиотека), я смог получить пару корпоративных приложений собирается прямо сейчас.

Он также работает с тем же редукционным инструментом. Это хорошая статья, которая охватывает некоторые из преимуществ.

Таким образом, для всех, кто прибыл на эту публикацию SO, ищущую "более простую редукцию", я рекомендую попробовать ее как простую альтернативу редуксу со всеми преимуществами и 1/4 от стандартного.

Ответ 8

Помимо технических аргументов, описанных в предыдущих ответах, ИМХО есть две важные причины:

  • Инструментарий: Redux dev tool - потрясающий инструмент, который делает ваш опыт разработчика/отладки невероятным (машина времени, возможность экспортировать сеанс пользователя и воспроизводить его в своем локальном окружении...).

  • Удобство: Redux получил более 51000 результатов по переполнению стека, поток 9000.

Ответ 9

Потому что поддержка Redux слишком велика против потока