Redux FAQ: Структура кода
Содержание
- Как должна выглядить моя файловая структура? Как я должен группировать генераторы экшенов и редюсеры в проекте? Где должны быть селекторы?
- Как я должен разделять логику между редюсерами и генераторами экшенов? Где должна быть "бизнес-логика"?
- Почему я должен использовать генераторы экшенов?
- Где должны находиться веб-сокеты и другие постоянные соединения
Структура кода
Как должна выглядить моя файловая структура? Как я должен группировать генераторы экшенов и редюсеры в проекте? Где должны быть селекторы?
Поскольку Redux - это просто библиотека хранения данных, у нее нет точного мнения о том, как ваш проект должен быть структурирован. Тем не менее, есть ряд общих паттернов, которые большинство разработчиков Redux склонны использовать:
- Rails-style: отдельные директории для “экшенов”, “констант”, “редюсеров”, “контейнеров” и “компонент”
- Domain-style: отдельные директории для фичи или домена, возможно, с поддиректориями для каждого типа файлов
- “Ducks”: похож на domain-style, но явно связывающий экшены и редюсеры, часто определяя их в том же файле
В целом предполагается, что селекторы определены наряду с редюсерами и экспортируются, а затем повторно используются в других местах (таких как, функции mapStateToProps
, асинхронные генераторы экшенов или саги) чтобы сосредоточить весь код, который знает о фактической форме дерева состояния в файлах редюсеров.
Тогда как, в конечном итоге, не имеет значения, как вы размещаете ваш код на диске, важно помнить, что экшены и редюсеры не следует рассматривать изолированно. Допускается (и рекомендуется) для редюсера, быть определенным в одной папке, чтобы реагировать на экшены, определенные в другой папке.
Дополнительная информация
Документация
Статьи
How to Scale React Applications (accompanying talk: Scaling React Applications)
My journey towards a maintainable project structure for React/Redux
React/Redux Links: Architecture - Project File Structure
Обсуждения
- #943: Reducer querying
- React Boilerplate #27: Application Structure
- Stack Overflow: How to structure Redux components/containers
- Twitter: There is no ultimate file structure for Redux
Как я должен разделять логику между редюсерами и генераторами экшенов? Где должна быть "бизнес-логика"?
Нет определенного четкого ответа на то, какие части логики следует переносить в редюсер, а какие в генератор экшенов. Некоторые разработчики предпочитают иметь "толстые" генераторы экшенов, с "тонкими" редюсерами, которые просто берут данные в экшене (action) и слепо добавляют их в соответствующее состояние.
Другие пытаются подчеркнуть, сохраняя экшенв, как можно маленькими, и свести к минимуму использование getState()
в генераторе экшенов. (Для целей данного вопроса, другие асинхронные подходы, такие, как саги и обзерваблы, попадают в категорию "генераторы экшенов")
Есть некоторая потенциальная выгода от использования большего количества логики в ваших редюсерах. Вероятно, что типы экшенов будут более семантическими и более значимыми (например, «USER_UPDATED» вместо «SET_STATE»). Кроме того, наличие большего количества логики в редюсеров означает, что больше функциональности будет зависеть от отладки путешествия во времени.
Этот комментарий красиво подводит итог этого разделения:
Теперь проблема в том, что поместить в генератор экшена, а что в редюсер, выбор между толстыми и тонкими объектами экшенов. Если вы кладете всю логику в генератор экшенов, вы в конечном итоге остаетесь с толстыми объектами экшенов, которые в своей основе декларируют обновления состояния. Редюсеры становятся чистыми, глупыми, добавлять, удалять, обновлять эти функции. Они будут легко композируемы. Но не так много бизнес-логики будет там. Если вы размещаете больше логики в редюсерах, вы в конечном итоге имеете красивые, тонкие объекты экшенов, большая часть вашей логики данных в одном месте, но ваши редюсеры сложнее составлять, т.к. вам может понадобиться информация из других веток. Вы в конечном итоге с большими редюсерами или редюсерами, которые принимают дополнительные аргументы выше в состоянии.
Найти баланс между этими двумя крайностями и вы освоите Redux.
Дополнительная информация
Статьи
- Where do I put my business logic in a React/Redux application?
- How to Scale React Applications
- The Tao of Redux, Part 2 - Practice and Philosophy. Thick and thin reducers.
Обсуждения
How putting too much logic in action creators could affect debugging
#384: The more that's in a reducer, the more you can replay via time travel
#1171: Recommendations for best practices regarding action-creators, reducers, and selectors
Twitter: Moving away from unclear terminology...
Почему я должен использовать генераторы экшенов?
Redux не требует генераторов экшенов. Вы можете создавать экшены любым удобным для вас способом, включая простую передачу литерала объекта в
dispatch
. Генераторы экшенов пришли из архитектуры Flux и были приняты сообществом Redux, потому что они предлагают несколько преимуществ.Генераторы экшенов более поддерживаемы. Обновления экшена могут быть сделаны в одном месте и применены везде. Все экземпляры экшена гарантированно имеют одинаковую форму и одинаковые значения по умолчанию.
Генераторы экшенов тестируемы. Правильность встроенного экшена должна быть проверена вручную. Как и любая функция, тесты для генератора экшена можно написать один раз и запустить автоматически.
Генераторы экшенов легче документировать. Параметры генератора экшена перечисляют зависимости экшена. А централизация определения экшена обеспечивает удобное место для комментариев к документации. Когда экшены записаны в строке, эту информацию сложнее собирать и передавать.
Генераторы экшенов - более мощная абстракция. Создание экшена часто включает преобразование данных или выполнение запросов AJAX. Генераторы экшенов предоставляют единый интерфейс для этой разнообразной логики. Эта абстракция упрощает компоненту при отправки экшена, не усложняя деталями его создания.
Дальнейшая информация
Статьи
Обсуждения
Где должны существовать веб-сокеты и другие постоянные соединения?
Мидлвар - это правильное место для постоянных соединений, типа веб-сокетов в Redux приложении, по ряду причин:
- Мидлвар существует на протяжении всего жизненного цикла приложения
- Как и в случае самого стора, вам, вероятно, нужен только один экземпляр данного соединения, который может использовать все приложение
- Мидлвару доступны все отправленные экшены и сами могу отправлять экшены. Это означает, что мидлвар может выполнять отправленные экшены и превращать их в сообщения, отправляемые через веб-сокет и отправлять новые экшены при получении сообщения через веб-сокет.
- Экземпляр подключения веб-сокета не сериализуем, поэтому он не принадлежит самому состоянию стора
См. этот пример, который показывает, как мидлвар сокетов может отправлять и реагировать на экшены Redux.
Существует множество мидлваров для веб-сокетов и других подобных соединений - см. ссылку ниже.
Библиотеки