Redux - это инструмент для управления состоянием данных и состоянием пользовательского интерфейса в приложениях Javascript. В этом руководстве мы увидим, как организовать структуру проектов, состоящих из Redux.

Redux - это контейнер с предсказуемым состоянием для приложений JavaScript. Он помогает вам писать приложения, которые ведут себя согласованно, работают в разных средах (клиентских, серверных и собственных) и легко тестируются. - https://redux.js.org/

Хотя Redux в значительной степени связан с React, его также можно использовать с другими библиотеками, такими как Vue, Meteor, Angular и т. Д. Он также легкий, около 2 КБ (включая зависимости), поэтому вам не нужно беспокоиться о размере приложения. слишком большой.

Поскольку мы избавились от определения Redux, давайте приступим к разработке протестированной, строго типизированной и масштабируемой архитектуры!

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

СОДЕРЖАНИЕ

Предпосылки

  • Node v10.x.x

Настройка проекта

Для начала мы будем использовать create-react-appwith typescript, но эту архитектуру также можно применить к любому существующему проекту:

$ yarn create react-app my-app --typescript

Затем мы можем перейти в каталог проекта и запустить приложение:

$ yarn start

Установка зависимостей

Очевидно, нам нужно установить зависимости, связанные с redux, в базе кода в другой командной строке в корневом каталоге проекта:

$ yarn add [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected]

Давайте также добавим зависимости разработки:

$ yarn add --dev @types/react-redux@7.1.1 @types/[email protected] @types/[email protected] @types/[email protected]

Интеграция Redux в проект

После установки нам нужно внести пару изменений в существующий код, чтобы подготовить базу кода для архитектуры Redux. Сначала удалите всю разметку внутри return. Затем добавьте разметку для поставщика redux с хранилищем redux и контейнером. Итоговый файл App.tsx будет выглядеть так:

Затем мы создадим statefolder внутри srcdirectory, чтобы сохранить файл конфигурации нашего хранилища и инициализацию для хранилища Redux.

$ mkdir src/state && touch src/state/index.ts

Чтобы иметь возможность настраивать промежуточное ПО в зависимости от среды, давайте создадим индексный файл, который будет импортировать конфигурацию хранилища. В этом руководстве мы останемся в среде разработки:

Затем нам нужно создать конфигурацию разработки инициализатора хранилища в том же каталоге:

В целях модульности состояний мы будем придерживаться подхода к структуре папок на основе функций. Что называется Утки. Подробнее об этом шаблоне можно узнать здесь: freeCodeCamp: https://www.freecodecamp.org/news/scaling-your-redux-app-with-ducks-6115955638be/

Итак, давайте создадим нашу первую папку с утками, в которой будут храниться другие утки (папки функций):

$ mkdir src/state/ducks && touch src/state/ducks/index.ts

Затем нам нужно создать корневой редуктор, который определяет состояние приложения:

Архитектура проекта Redux

Архитектура Redux основана на строгом однонаправленном потоке данных.

Это означает, что все данные в приложении подчиняются одному и тому же шаблону жизненного цикла, что делает логику вашего приложения более предсказуемой и простой для понимания. Это также способствует нормализации данных, так что вы не получите несколько независимых копий одних и тех же данных, которые не знают друг о друге. - https://redux.js.org/basics/data-flow

В этой архитектуре поток данных выглядит следующим образом:

  • Компонент обрабатывает событие и отправляет действие
  • Redux вызывает функции редуктора
  • Связанная функция редуктора обновляет состояние
  • Контейнеры, которые ожидают изменения этого сегмента состояния, получают уведомление
  • Контейнеры обновляют компонент с новым состоянием и реквизитами
  • Компонент перерисовывается при изменении реквизита

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

Продолжим реализацию потока данных. Во-первых, нам нужен один общедоступный API. Для этого воспользуемся JSONPlaceholder.

Чтобы сохранить URL-адрес api, нам нужно создать файл .env. Не забудьте перезапустить сервер npm после добавления следующих строк:

// .env
REACT_APP_JSON_PLACEHOLDER=https://jsonplaceholder.typicode.com

Для простоты в этом руководстве мы реализуем только запрос GET. Но вы можете легко выполнить POST, создав новые действия, которые несут полезную нагрузку для отправки в конечную точку API. Чтобы сделать его типизированным, вы также должны изменить типы действий на основе этого. Исходя из этого, наша масштабируемая архитектура и структура папок выглядят так:

src
├── App.css
├── App.test.tsx
├── App.tsx
├── components
│   ├── post.tsx
│   └── postList.tsx
├── containers
│   ├── __tests__
│   │   └── postList.container.spec.tsx
│   └── postList.tsx
├── index.css
├── index.tsx
├── logo.svg
├── react-app-env.d.ts
├── serviceWorker.ts
└── state
    ├── configureStore.dev.ts
    ├── ducks
    │   ├── index.ts
    │   └── post
    │       ├── __tests__
    │       │   ├── __mockData__
    |       |   |  └── postsData.json    
    |       │   ├── actions.spec.ts
    │       │   ├── reducers.spec.ts
    │       │   └── sagas.spec.ts
    │       ├── actions.ts
    │       ├── reducers.ts
    │       ├── sagas.ts
    │       └── types.ts
    ├── index.ts
    ├── middlewares
    │   └── saga.ts
    └── utils
        └── apiCaller.ts

Поскольку у нас будут операции для posts в нашем API, имя папки будет называться post. Также внутри него будет создана папка с тестовыми и макетными данными:

$ mkdir src/state/ducks/post src/state/ducks/post/__tests__ src/state/ducks/post/__tests__/__mockData__

Кроме того, нам нужно хранить в этой папке связанные типы для этой функции. Добавьте связанные типы в файл типов: type

Нам потребуются фиктивные данные для нашей postfeature, которые выглядят так:

Действия

Мы начнем с написания наших действий для нашей postfeature. Для простоты мы не будем рассматривать обработку ошибок в этом руководстве. Сначала мы начнем писать тесты:

Затем напишите фактические действия:

Редукторы

Нам нужны редукторы для формирования нашего состояния. Приступим к реализации с тестов:

Фактический редуктор будет выглядеть так:

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

Промежуточное ПО

Поскольку мы хотим, чтобы наши действия и редукторы были чистыми, нам нужно разобраться с этим в другом месте. Лучше всего использовать какое-то промежуточное программное обеспечение, которое может прослушивать действия и отправлять другие действия в Redux. Есть несколько вариантов, но для этого урока мы будем использовать Redux-Saga. Здесь мы также будем выполнять наши вызовы Ajax.

Для хранения промежуточного программного обеспечения мы создадим новую папку с именем middlewares внутри statedirectory:

$ mkdir src/state/middlewares && touch src/state/middlewares/sagas.ts

Давайте создадим промежуточное ПО для саги, чтобы использовать его при инициализации нашего магазина:

Чтобы использовать Redux-saga, нам нужно добавить наше новое промежуточное ПО для хранения конфигурации следующим образом:

Как всегда, начнем с написания тестов. С redux-saga-test-planpackage писать тесты для саг довольно просто:

Далее мы напишем нашу первую сагу для прослушивания определенных действий:

Нам также нужно создать одну корневую сагу, чтобы разветвить все саги о функциях в нашей базе кода:

Звонки Ajax

Мы начнем с создания новой папки, в которой будут храниться наши государственные утилиты:

$ mkdir src/state/utils && touch src/state/utils/apiCaller.ts

Для вызова API мы будем использовать встроенный метод fetch. Мы реализуем это, создав служебную функцию с именем apiCaller.

Контейнеры

Рекомендуется различать компоненты контейнера и компоненты представления. Компоненты контейнера служат мостом между хранилищем Redux и компонентами презентации. Компоненты контейнера получают данные из хранилища redux и предоставляют данные и действия для презентационных компонентов. Они, как правило, сохраняют состояние.

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

$ mkdir src/containers src/containers/__test__

Начнем сначала писать тесты для контейнера:

Далее идет фактический код контейнера:

Завершим это созданием компонентов презентаций:

$ mkdir src/components

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

Что следующее?

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

  • редуктор-регистратор
  • сокращение-devtools-расширение

Заключение

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

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

Ваше здоровье!