Comments 17
Как правильно произвести декомпозицию редьюсеров, то есть создать несколько независимых редьюсеров, которые преобразуют независимые состояния, и затем объединить их в один редьюсер? Если создать несколько редьюсеров через redux-symbiote и объединить их через combineReducers, то возникнет риск коллизии названий типов действий (потому что они не записаны в коде явно).
+2
Спасибо за вопрос. `createSymbiote` имеет третий параметр namespace/options, с помощью которого можно задать префикс для всех экшен-типов сразу.
github.com/sergeysova/redux-symbiote#options
Некоторые примеры использования symbiote можно посмотреть здесь: github.com/howtocards/frontend/tree/dev/src/features/cards/symbiotes
github.com/sergeysova/redux-symbiote#options
const { actions, reducers } = createSymbiote(
initialState, symbiotes, 'prefix/namespace'
)
// or
const { actions, reducers } = createSymbiote(
initialState,
symbiotes,
{ namespace: 'prefix/namespace' },
)
Некоторые примеры использования symbiote можно посмотреть здесь: github.com/howtocards/frontend/tree/dev/src/features/cards/symbiotes
+1
Мы как-то сделали себе похожий велик на одном проекте на TypeScript. Получилось ну очень похоже:
В отличии от велика из статьи, тут все строго типизировано. Например, типы actionCreator-ов и их параметров выводятся (мы ради этого карировали функции, action => state => state вместо (action, state) => state).
Плюс имена экшнов автоматом строятся, и никаких функций в action-ы не упаковывается. Т.е. в нашем случае actionCreators.set({ value: 10 }) => { type: 'COUNTER_SET', value: 10 }.
Вот тут исходники самой утилитки: gist.github.com/jakobz/ae3e5567e20fff3d66d9e8852a9a655a
const initialState: CounterState = {
current: 0
}
const next = ({ }) => (s: MyState) => ({ ...s, current: s.current + 1 });
const set = (a: { value: number}) => (s: MyState) => ({ ...s, current: s.current + a.value });
const { actionCreators, bindActions, reducer } = buildReducer(
initialState,
{
next,
set,
},
{ prefix: "COUNTER" }
);
В отличии от велика из статьи, тут все строго типизировано. Например, типы actionCreator-ов и их параметров выводятся (мы ради этого карировали функции, action => state => state вместо (action, state) => state).
Плюс имена экшнов автоматом строятся, и никаких функций в action-ы не упаковывается. Т.е. в нашем случае actionCreators.set({ value: 10 }) => { type: 'COUNTER_SET', value: 10 }.
Вот тут исходники самой утилитки: gist.github.com/jakobz/ae3e5567e20fff3d66d9e8852a9a655a
+4
Я позволю себе скопипастить сюда свое сообщение из другой темы:
Итак имеем:Я так и не нашел ответа на вопрос зачем нужны эти псевдоабстракции.
— Глобальный стор (обычно все глобальное — плохо, а тут вдруг — хорошо).
— Кучу экшенов где action.type уникален в пределах приложения.
— Кучу action creator-ов c названием, в большинстве случаев, таким же как action.type, записанным в другом регистре.
— reducer-ы — по сути обычный switch case.
Теоретически, для уменьшения бойлерплейта вы даже использовали какую-нибудь свистоперделку.
Вопрос:
Где в этом хозяйстве архитектура, абстракции и изоляции и чем оно координально лучше, чем обычные методы хранилища? ЗЫ: Методы хотя бы можно комбинировать в отличии от словоблудия внутри switch case.
+3
Спасибо за вопросы.
Сразу оговорюсь, что статья не об архитектуре в целом, а только об инструменте, который позволяет уменьшить количество кода, повысить читабельность и структурировать часть архитектуры redux.
Не считаю, что глобальный стор или несколько распределенных, а также вызов напрямую методов или через дополнительную инфраструктуру это плохо или хорошо. Каждый использует при разработке, что ему удобнее и подходит для реализации.
Архитектура redux неплохо описана в документации и легко бьется на слои:
— стор отдельно, что и как сделать со стором отдельно,
— представление: глупые компоненты, контейнеры, селекторы данных,
— для перехвата действий и последующего комбинирования действий над стором (и не только), например, redux-saga.
Все это можно легко передавать между проектами и тестировать.
Идеального решения нет, как и ответа на все вопросы.
Сразу оговорюсь, что статья не об архитектуре в целом, а только об инструменте, который позволяет уменьшить количество кода, повысить читабельность и структурировать часть архитектуры redux.
Не считаю, что глобальный стор или несколько распределенных, а также вызов напрямую методов или через дополнительную инфраструктуру это плохо или хорошо. Каждый использует при разработке, что ему удобнее и подходит для реализации.
Архитектура redux неплохо описана в документации и легко бьется на слои:
— стор отдельно, что и как сделать со стором отдельно,
— представление: глупые компоненты, контейнеры, селекторы данных,
— для перехвата действий и последующего комбинирования действий над стором (и не только), например, redux-saga.
Все это можно легко передавать между проектами и тестировать.
Идеального решения нет, как и ответа на все вопросы.
+1
Как было нечитебильное г, так и осталось
+1
Не понятно как на такие действия подписываться в том же redux-saga? У них можно имя получить, через какой-то условный name?
yield takeEvery(actions.open.success.name, loadAdditional)
будет работать?+1
Как вижу подобный код и реализацию — честно, плакать хочется. Ну вот реально вьехать с пол пинка вряд ли получится. Далее все что только можно суем в глобальный стор. Туда жа запихавают логику приложения. Вот попробуйте потом такое приложение оптимизировать. Разбить на слои, где с каждым слоем работала бы команда.
Почему не вынести бизнес логику получения и обработки данных в отдельные слои? Зачем все держать в сторе, если данные нужны только в одном месте? Как сделать что-то не завязываясь на redux?
В большинстве туториалов пишут о том, что это серебряная пуля, вот берем и радость. Как сказал один девелопер у меня в команде — «чувак, ты не понимаешь?! Это же React-way! Надо только так писать, так в мануалах пишут». Над… В общем, на практике, это просто добавляет проблем, нежели профита.
Что делаю у себя в проектах, это в первую очередь разделяю приложение на слои: бизнес логика, API, компоненты, Store.
— API это набор классов, где реализована коммуникация с сервером
— бизнес логика, слой где обрабатываются и подготавливаются данные
— компоненты, по содержат логику только для отрисовки интерфейса, максимально стараемся делать их независимыми, маленькими и тупыми.
— Store. В сторе держим только те данные, которые нужны нескольким компонентам в одно и тоже время на странице. К примеру, профиль пользователя. Имя пользователя покажем в хедере сайта, в навигационном меню и на странице профиля пользователя. Изменили имя, поменялось в трех точках.
Как видно из описания, нет проблем разделить работы между людьми. Не жестких привязок. В любой момент можно заменить слой на другую технологию, не переписывая все остальное.
Почему не вынести бизнес логику получения и обработки данных в отдельные слои? Зачем все держать в сторе, если данные нужны только в одном месте? Как сделать что-то не завязываясь на redux?
В большинстве туториалов пишут о том, что это серебряная пуля, вот берем и радость. Как сказал один девелопер у меня в команде — «чувак, ты не понимаешь?! Это же React-way! Надо только так писать, так в мануалах пишут». Над… В общем, на практике, это просто добавляет проблем, нежели профита.
Что делаю у себя в проектах, это в первую очередь разделяю приложение на слои: бизнес логика, API, компоненты, Store.
— API это набор классов, где реализована коммуникация с сервером
— бизнес логика, слой где обрабатываются и подготавливаются данные
— компоненты, по содержат логику только для отрисовки интерфейса, максимально стараемся делать их независимыми, маленькими и тупыми.
— Store. В сторе держим только те данные, которые нужны нескольким компонентам в одно и тоже время на странице. К примеру, профиль пользователя. Имя пользователя покажем в хедере сайта, в навигационном меню и на странице профиля пользователя. Изменили имя, поменялось в трех точках.
Как видно из описания, нет проблем разделить работы между людьми. Не жестких привязок. В любой момент можно заменить слой на другую технологию, не переписывая все остальное.
0
Как потом эти бизнес слои связывать вместе используя Flux?
Как это дебажить без вменяемых dev-tools?
redux-symbiote был призван решить только одну проблему: убрать бойлерплейт вокруг экшенов и редюссеров, ни больше, ни меньше.
symbiote — чисто апдейтеры стора, thunk/execute — бизнес-логика, components — отображение данных. Всё тоже самое разделение на слои, только более простое.
Разделять приложение между командами нужно полноценно разделяя приложение на micro-frontends, а не работать всем вместе в огромном монолите.
А вот по поводу качественного разделения: я постепенно перехожу на effector. Где есть и полноценный дебаг и статическое вычисление зависимых сторов, и красивое API, и отстутствие проблемы ромбовидных зависимостей.
Мб потом статью о нём напишу.
Как это дебажить без вменяемых dev-tools?
redux-symbiote был призван решить только одну проблему: убрать бойлерплейт вокруг экшенов и редюссеров, ни больше, ни меньше.
symbiote — чисто апдейтеры стора, thunk/execute — бизнес-логика, components — отображение данных. Всё тоже самое разделение на слои, только более простое.
Разделять приложение между командами нужно полноценно разделяя приложение на micro-frontends, а не работать всем вместе в огромном монолите.
А вот по поводу качественного разделения: я постепенно перехожу на effector. Где есть и полноценный дебаг и статическое вычисление зависимых сторов, и красивое API, и отстутствие проблемы ромбовидных зависимостей.
Мб потом статью о нём напишу.
+1
Разбить на слои, где с каждым слоем работала бы команда.
Вообще нет проблем разбить на слои.
В данном случае redux-symbiote позволяет уменьшить количество кода, повысить читабельность и структурировать часть архитектуры redux.
У нас все проекты послойные:
— стор (redux)
— что и как сделать со стором redux-symbiote,
— представление: глупые компоненты, контейнеры (модули), селекторы данных (как раз группируют данные для контейнеров из разных частей стора),
— бизнес логика — redux-saga,
— апи и сервисы с возможностью моков.
Уже проектов 10+ с использованием redux разработано — проблем не возникает.
Абсолютно не понимаю зачем этот холивар глобальный стор vs распределенный. Статья не об этом. Каждый выбирает инструмент по необходимости.
0
Я не понимаю, почему люди не переходят на elm, если вам так важно убрать бойлерплейт код, что вы готовы создовать либы вокруг редакса чтоб от него избавится. Ведь редакс пришел именно из ельма, и там те же экшены и редюсер выглядит наиболее выгодно и локанично. Вот тот же пример на elm:
type alias Model =
{ loading : Bool
, error : Just String
, popupsOpened : List String
}
init : Model
init =
{ loading = True
, error = Nothing
, popupsOpened = ["popup1", "popup2", "popup3"]
}
type FetchingStatus
= Start String
| Fail String
| Success String
type Msg
= Open FetchingStatus
| Close FetchingStatus
update : Msg -> Model -> Model
update msg model =
case msg of
Open status ->
case status of
Start ->
{ model | loading = True, error = Nothing }
Fail error ->
{ model | error = Just error }
Success popupName ->
{ model | popupsOpened = model.popupsOpened :: popupName }
Close status ->
case status of
Start ->
{ model | loading = True, error = Nothing }
Fail error ->
{ model | error = Just error }
Success popupName ->
{ model | popupsOpened = List.filter (\x -> x not popupName) model.popupsOpened }
0
Sign up to leave a comment.
Redux-symbiote — пишем действия и редьюсеры почти без боли