Если магазины поддерживают свое собственное состояние и имеют возможность при этом вызывать службы сети и хранения данных ... и в этом случае действия просто бессмысленные отправители сообщений,
-ИЛИ-
... должны ли магазины быть глупыми получателями неизменяемых данных из действий (а действия должны быть теми, которые извлекают / отправляют данные между внешними источниками? Магазин в этом случае будет действовать как модели представления и сможет агрегировать / фильтровать их data до установки своей собственной базы состояний на неизменяемых данных, которые они получили в результате действия.
Мне кажется, что это должно быть одно или другое (а не сочетание того и другого). Если да, то почему одно предпочтительнее / рекомендуется другому?
reactjs
reactjs-flux
plaxdan
источник
источник
Ответы:
Я видел, как шаблон потока реализован в обоих направлениях, и после того, как я сделал и то, и другое (изначально придерживаясь первого подхода), я считаю, что хранилища должны быть глупыми получателями данных от действий, и что асинхронная обработка записей должна находиться в создатели действий. ( Асинхронное чтение можно обрабатывать по-разному .) По моему опыту, это дает несколько преимуществ в порядке важности:
Ваши магазины становятся полностью синхронными. Это значительно упрощает отслеживание и тестирование логики вашего хранилища - просто создайте экземпляр хранилища с некоторым заданным состоянием, отправьте ему действие и проверьте, изменилось ли состояние должным образом. Более того, одна из основных концепций в потоке - предотвращение каскадных отправок и предотвращение одновременных отправок нескольких; это очень сложно сделать, когда ваши магазины выполняют асинхронную обработку.
Все отправления действий происходят от создателей действий. Если вы обрабатываете асинхронные операции в своих магазинах и хотите, чтобы обработчики действий ваших магазинов были синхронными (и вы должны это сделать, чтобы получить гарантии однократной отправки потока), ваши магазины должны будут запускать дополнительные действия SUCCESS и FAIL в ответ на асинхронные обработка. Размещение этих отправлений в создателях действий помогает разделить работу создателей действий и магазинов; Более того, вам не нужно копаться в логике вашего магазина, чтобы выяснить, откуда отправляются действия. Типичное асинхронное действие в этом случае может выглядеть примерно так (измените синтаксис
dispatch
вызовов в зависимости от типа используемого потока):Логику, которая в противном случае может дублироваться в различных действиях, следует выделить в отдельный модуль; в этом примере это модуль
SomeDataAccessLayer
, который выполняет фактический запрос Ajax.Вам нужно меньше создателей действий. Это не так уж важно, но приятно иметь. Как упоминалось в № 2, если в ваших магазинах есть синхронная обработка диспетчеризации действий (а она должна), вам необходимо запустить дополнительные действия для обработки результатов асинхронных операций. Выполнение диспетчеризации в создателях действий означает, что один создатель действия может отправлять все три типа действий, обрабатывая результат самого асинхронного доступа к данным.
источник
"SOME_ACTION"
), использую API для создания запроса (SomeDataAccessLayer.doSomething(userId)
), который возвращает обещание, и в двух.then
функциях отправляю дополнительные действия. Состояние запроса может (более или менее) отображать состояние хранения, если приложению необходимо знать о состоянии состояния. Как это соотносится с приложением (например, может быть, каждый комментарий имеет отдельное состояние ошибки, а-ля Facebook, или, может быть, есть один глобальный компонент ошибки)Я написал этот вопрос разработчикам в Facebook, и ответ, который я получил от Билла Фишера, был:
источник
a call from store works better when action triggers from non-human driver
?Хранилища должны делать все, включая выборку данных и сигнализацию компонентам о том, что данные хранилища были обновлены. Зачем? Потому что действия могут быть легкими, одноразовыми и заменяемыми, не влияя на важное поведение. Все важные функции и функции происходят в магазине. Это также предотвращает дублирование поведения, которое иначе было бы скопировано в двух очень похожих, но разных действиях. Магазины - ваш единственный источник (обработки) правды.
В каждой реализации Flux, которую я видел, Действия - это в основном строки событий, превращенные в объекты, как обычно у вас будет событие с именем «anchor: clicked», но в Flux оно будет определено как AnchorActions.Clicked. Они даже настолько «глупы», что в большинстве реализаций есть отдельные объекты Dispatcher для фактической отправки событий в хранилища, которые их слушают.
Лично мне нравится реализация Flux Reflux, в которой нет отдельных объектов Dispatcher, а объекты Action осуществляют диспетчеризацию сами.
edit: Facebook Flux на самом деле выбирает «создателей действий», поэтому они действительно используют умные действия. Они также подготавливают полезную нагрузку, используя магазины:
https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/actions/ChatMessageActionCreators.js#L27 (строки 27 и 28)
После этого обратный вызов по завершении запустит новое действие, на этот раз с полученными данными в качестве полезной нагрузки:
https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/utils/ChatWebAPIUtils.js#L51
Думаю, это лучшее решение.
источник
Я приведу аргумент в пользу «тупых» действий.
Возлагая ответственность за сбор данных о представлениях в свои Действия, вы связываете свои Действия с требованиями к данным ваших представлений.
Напротив, общие действия, которые декларативно описывают намерение пользователя или некоторый переход состояния в вашем приложении, позволяют любому хранилищу, которое реагирует на это действие, преобразовывать намерение в состояние, специально адаптированное для представлений, на которые оно подписано.
Это подходит для более многочисленных, но более мелких и более специализированных магазинов. Я выступаю за этот стиль, потому что
Цель магазина - предоставить данные для представлений. Название «Действие» подсказывает мне, что его цель - описать изменение в моем приложении.
Предположим, вам нужно добавить виджет к существующему представлению Dashboard, в котором отображаются новые причудливые агрегированные данные, которые только что развернула ваша бэкэнд-группа.
При использовании «умных» действий вам может потребоваться изменить действие «refresh-dashboard», чтобы использовать новый API. Однако «Обновление дашборда» в абстрактном смысле не изменилось. Требования к данным ваших представлений - вот что изменилось.
С помощью «глупых» действий вы можете добавить новое хранилище для нового виджета и настроить его так, чтобы при получении типа действия «refresh-dashboard» он отправлял запрос на новые данные и предоставлял их новый виджет, когда он будет готов. Мне кажется логичным, что когда слою представления требуется больше или других данных, то, что я меняю, является источником этих данных: хранилищами.
источник
Flux-React-Router -демонстрация от компании Gaeron есть хорошая служебная вариация «правильного» подхода.
ActionCreator генерирует обещание из внешней службы API, а затем передает обещание и три константы действия
dispatchAsync
функции в прокси / расширенном диспетчере.dispatchAsync
всегда будет отправлять первое действие, например, «GET_EXTERNAL_DATA», и как только обещание вернется, оно отправит либо «GET_EXTERNAL_DATA_SUCCESS», либо «GET_EXTERNAL_DATA_ERROR».источник
Если вы хотите, чтобы в один прекрасный день среда разработки была сопоставима с тем, что вы видите в знаменитом видео Брета Виктора « Изобретения по принципу» , вам лучше использовать немые хранилища, которые представляют собой просто проекцию действий / событий внутри структуры данных без каких-либо побочных эффектов. Также было бы полезно, если бы ваши магазины были фактически членами одной и той же глобальной неизменяемой структуры данных, как в Redux. .
Дополнительные объяснения здесь: https://stackoverflow.com/a/31388262/82609
источник