Асинхронный Redux без Middlewares  - используем ES2017

Асинхронный Redux без Middlewares  - используем ES2017

Перевод статьи Asynchronous Redux Without Middlewares — Using ES2017

Можно ли обрабатывать асинхронные redux actions без middlewares, а с ES2017 async/await? Мы можем сделать это более понятным способом.

Должен ли я это делать?

Я здесь не для того, чтобы говорить, что вы не должны использовать thunk или saga. Если вы предпочитаете, вы можете представить что это упражнение, которое поможет нам углубить наши знания о redux и функциональном программировании. Кроме того, мы собираемся сделать все это тестируемым.

Проект

Мы собираемся создать простой React проект для использования GitHub API для поиска в репозиториях по имени пользователя. Если вы хотите посмотреть на конечный продукт, перейдите по ссылке ниже:

https://async-redux-without-middleware.herokuapp.com

Давайте покодим

Мы собираемся использовать create-react-app CLI:

npx create-react-app async-redux-without-middlewares
cd async-redux-without-middlewares

Давайте также установим зависимости

npm install -s redux react-redux axios

Http сервис

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

services/repos.js

Action

actions/repos.js

Экспортируемая функция getReposByUsernameInjector будет использоваться для connect() нашего основного контейнера. На него не будут ссылаться, но после выполнения результат станет свойством компонента.

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

Connecting

В react контейнеры - это компоненты, которые подключаются к redux state. Мы собираемся отделить connection от самого компонента.

components/Main.js

containers/ConnectedMain.js

Второй параметр connect() - это вызываемая функция mapDispatchToProps, которая позволяет вам создавать функции, которые диспатчатся при вызове и передают свойства результирующего объекта как props вашему компоненту.

Если вы хотите узнать больше о actions dispatching, я настоятельно рекомендую прочитать эту страницу из документации по redux.

https://react-redux.js.org/using-react-redux/connect-mapdispatch

После подключения все это выглядит так:

2

Как это тестировать?

Сервис

Чтобы протестировать наш сервис, нам просто нужно вызвать пользовательский объект как axios и ожидать, что get() функция вызовется с URL-адресом репозитория.

services/repos.test.js

The action

Чтобы проверить наши действия, мы настроим пользовательский dispatch() и сервис для имитации четырех возможностей: успешно, пустые репозитории, имя пользователя не найдено и ошибка подключения.

actions/repos.test.js

Контейнер

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

Другие компоненты

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

https://github.com/andregardi/async-redux-without-middlewares

Примечание. Я добавил в окончательный проект @material-ui/core и @material-ui/icons для визуальных компонентов, и express для размещения статических серверов на Heroku.

Присоединяйтесь к нашим каналам FrontEndDev и Web Stack в Telegram, чтобы не пропустить самое интересное из мира Web!