Redux Middleware – что это такое и как его собрать с нуля

В этой статье мы рассмотрим, что такое промежуточное ПО в Redux, почему оно используется и как вы можете создать собственное промежуточное ПО с нуля.

Хотите изучить Redux с нуля и создать полноценное приложение для заказа еды с интеграцией полосовой оплаты? Посмотрите мой курс Mastering Redux .

Итак, приступим.

Что такое промежуточное ПО Redux?

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

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

Взгляните на приведенный ниже код:

import React from "react";
import ReactDOM from "react-dom";
import { createStore } from "redux";

const reducer = (state = 0, action) => {
  switch (action.type) {
    case "INCREMENT":
      return state + action.payload;
    case "DECREMENT":
      return state - action.payload;
    default:
      return state;
  }
};

const store = createStore(reducer);

store.subscribe(() => {
  console.log("current state", store.getState());
});

store.dispatch({
  type: "INCREMENT",
  payload: 1
});

store.dispatch({
  type: "INCREMENT",
  payload: 5
});

store.dispatch({
  type: "DECREMENT",
  payload: 2
});

Вот демонстрация песочницы кода .

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

Как я объяснил в этой статье, createStore функция принимает три аргумента:

  • первый аргумент – это функция, которая обычно известна как редуктор – обязательный аргумент
  • второй аргумент – начальное значение состояния – необязательный аргумент
  • третий аргумент – промежуточное ПО – необязательный аргумент

Как создать промежуточное ПО в React

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

import { applyMiddleware } from "redux";

Допустим, мы создаем loggerMiddleware. Затем для определения промежуточного программного обеспечения нам нужно использовать следующий синтаксис:

const loggerMiddleware = (store) => (next) => (action) => {
  // your code
};

Приведенный выше код эквивалентен приведенному ниже коду:

const loggerMiddleware = function (store) {
  return function (next) {
    return function (action) {
      // your code
    };
  };
};

Как только функция промежуточного программного обеспечения создана, мы передаем ее applyMiddleware функции следующим образом:

const middleware = applyMiddleware(loggerMiddleware);

И, наконец, мы передаем промежуточное ПО в createStore функцию следующим образом:

const store = createStore(reducer, middleware);

Несмотря на то, что мы упоминали выше, что промежуточное ПО является третьим аргументом createStore функции, второй аргумент (начальное состояние) не является обязательным. Таким образом, в зависимости от типа аргументов createStore функция автоматически определяет, что переданный аргумент является промежуточным программным обеспечением, поскольку он имеет особый синтаксис вложенных функций.

Вот обновленная демонстрация тестовой среды кода для приведенного выше кода.

В приведенной выше демонстрации песочницы кода это loggerMiddleware выглядит так:

const loggerMiddleware = (store) => (next) => (action) => {
  console.log("action", action);
  next(action);
};

Вот ссылка для предварительного просмотра вышеприведенной демонстрации Code Sandbox.

Если вы проверите консоль, вы увидите следующий вывод:

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

Что же произойдет, если мы не вызовем nextфункцию внутри loggerMiddleware?

Тогда действие не будет отправлено редуктору, поэтому хранилище не будет обновляться. Если вы работали с Node.js, вы можете найти его похожим на то, как промежуточное ПО работает в Node.js.

В промежуточном программном обеспечении Node.js также, если мы не вызываем следующую функцию, запрос не будет отправлен вперед.

Вот обновленная демонстрация песочницы кода с удаленным вызовом следующей функции.

const loggerMiddleware = (store) => (next) => (action) => {
  console.log("action", action);
};

Вот ссылка для предварительного просмотра вышеприведенной демонстрации Code Sandbox.

Если вы проверите консоль, вы увидите следующий вывод:

Как видите, мы получаем только те действия, которые записываются в консоль. И поскольку действие не перенаправляется редуктору, оно не будет выполнено, поэтому мы не видим console.log из store.subscribe функции. Как описано ранее, мы можем изменить действие из промежуточного программного обеспечения до того, как оно будет отправлено редуктору.

Вот обновленная демонстрация песочницы кода, в которой мы изменяем полезную нагрузку действия перед его отправкой редуктору.

Код промежуточного программного обеспечения выглядит так:

const loggerMiddleware = (store) => (next) => (action) => {
  console.log("action", action);
  action.payload = 3;
  next(action);
};

Вот ссылка для предварительного просмотра вышеприведенной демонстрации Code Sandbox.

Согласно коду, как только действие записывается в консоль, мы устанавливаем полезную нагрузку действия на значение 3. Таким образом, действие typeостается тем же, но payloadизменяется. Таким образом, мы видим, что изначально состояние изменилось на 3. Затем он снова увеличивается на 3, что делает его 6. Наконец, он уменьшается на 3, делая окончательное значение состояния 3.

Перед тем, как действие будет отправлено в редуктор, наш вызывается, loggerMiddleware где мы меняем значение полезной нагрузки, и мы всегда устанавливаем его на 3 перед отправкой в ​​редуктор. Таким образом, в зависимости от типа действия INCREMENT или DECREMENT редуктор всегда будет изменен на значение 3.

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

Редукторы должны быть чистой функцией, и мы не должны вносить никаких изменений в состояние и действия внутри редуктора. Вы можете узнать больше об этом в моем курсе «Освоение Redux» .

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

const middleware = applyMiddleware(loggerMiddleware, secondMiddleware, thirdMiddleware);

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

Спасибо за прочтение!

Ответить