Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Мидлвары JS: Redux (React)

Мидлвары (middlewares) — это функции, которые последовательно вызываются в процессе обновления данных в хранилище. Они относятся к продвинутым техникам использования Redux.

В этом уроке мы разберем, как подключать и использовать мидлвары. Они помогают нам подключать различные библиотеки, причем с самого начала использования их в React.

Как работают мидлвары

Общий принцип такой:

  • Сначала мидлвары встраиваются в хранилище при его создании
  • Затем во время диспатчинга (отправки действий) данные проходят через мидлвары и только затем попадают в редьюсер

Схематично этот принцип можно показать так:

Работа мидлваров в Redux

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

Мидлвары используются в таких задачах, как:

  • Логирование
  • Оповещение об ошибках
  • Работа с асинхронным API
  • Маршрутизация

Как устроены мидлвары

Рассмотрим типичную структуру мидлвары, которая отвечает, например, за логирование. Логирование будем осуществлять с помощью методов console.info(), console.groupEnd(), console.log(). Любая мидлвара в Redux — это композиция из трех вложенных функций:

// Мидлвара со вложенными стрелочными функциями
const logger = (store) => (next) => (action) => {
  console.group(action.type);
  console.info('dispatching', action);
  const result = next(action);
  console.log('next state', store.getState()); // выводим текущее состояние в консоль
  console.groupEnd();
  return result;
};

У всех мидлвар одинаковая структура из трех компонентов. Рассмотрим ее на примере выше:

  1. Внешняя функция

    Именно она является мидлварой и передается в метод applyMiddleware(). Функция получает на вход объект store, который содержит методы dispatch() и getState() для работы с флоу Redux.

  2. Первая вложенная функция

    Её аргументом будет особая функция next(). Вызов этой функции в теле мидлвары с действием в качестве аргумента может прокидывать действие дальше по цепочке мидлвар.

    Но если next() вызван в последней мидлваре в цепочке (цепочка может состоять и из одной мидлвары), она диспатчит действие, отправляя его в редьюсер и вызывая обновление стейта.

  3. Вторая вложенная функция

    Это функция, принимающая в качестве аргумента действие action при его диспатчинге. Всякое действие в приложении, отправляемое в редьюсер, будет перехватываться мидлварой.

Мидлвара может содержать асинхронную логику. В этом случае логгер не блокирует обновление стора, действие передаётся по цепочке мидлвар вплоть до редьюсера, вызывая обновление стейта строчкой const result = next(action);.

Только потом, уже после цепочки мидлвар и обновления стейта, мы логируем новое состояние стора. Таким образом, все инструкции в логгере после вызова next() выполняются как бы в будущем, в котором последующие мидлвары и редьюсер уже закончили работу.

Рассмотрим другой пример:

const addFinishText = (store) => (next) => async (action) => {
  const result = next(action);
  if (action.type !== 'TASK_FINISH') {
    return result;
  }

  const user = await axios.get(`/users/${result.payload.userId}`);
  result.payload.task.text = [result.payload.task.text, `Задачу завершил ${user.name}`].join('. ');
  return result;
};

Мидлвара добавляет текст о завершении задачи с именем пользователя, кто завершил эту задачу. Она проверяет тип действия, если тип не относится к завершению задачи 'TASK_FINISH', то мидлвара завершает работу. Если тип соответствует, то делается запрос на получение данных о пользователе и обновляется текст в результирующих данных.

Как использовать мидлвары

Теперь посмотрим, как подключить мидлвары:

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';

const store = createStore(
  reducer,
  applyMiddleware(thunk)
)

Выше вы видите мидлвару thunk. Перед тем, как передать ее в функцию createStore, нужно применить к ней функцию applyMiddleware. Таким образом стор узнает о существовании мидлвары.

В общем случае она принимает три параметра:

  • Редьюсер
  • Начальное состояние
  • Мидлвары

Передача начального состояния и мидлвары опциональны. В примере выше мидлвара передается вторым параметром. Функция createStore проверяет тип второго параметра и в зависимости от этого понимает, что перед ней: начальное состояние или мидлвара.

Если мидлвар несколько, придется воспользоваться еще одной функцией:

import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import logger from 'redux-logger';

const store = createStore(
  reducer,
  /* preloadedState, */
  compose(
    applyMiddleware(thunk),
    applyMiddleware(logger)
  ),
)

В этом случае в хранилище передается результат функции compose(), при этом функция compose() принимает на вход мидлвары.

Теперь мы подобрались к главному. Для Redux написано специальное браузерное расширение Redux DevTools. Установите его в свой браузер.

Расширение для Redux

Ниже код подключения этого расширения к хранилищу:

const reduxDevtools = window.__REDUX_DEVTOOLS_EXTENSION__;
const store = createStore(
   reducer,
   /* preloadedState, */
    reduxDevtools && reduxDevtools(),
 );

Обратите внимание, что при работе с расширением функция applyMiddleware не требуется.

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


Дополнительные материалы

  1. Официальная документация ReduxDevTools

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Для полного доступа к курсу нужен базовый план

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

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 6 300 ₽ в месяц
Разработка фронтенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 1 июня
профессия
от 10 080 ₽ в месяц
Разработка фронтенд- и бэкенд-компонентов для веб-приложений
16 месяцев
с нуля
Старт 1 июня

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»