Redux中间件 - 它是什么以及如何从头开始构建它

115 阅读4分钟

在这篇文章中,我们将探讨Redux中的中间件是什么,为什么会用到它,以及如何从头开始创建自己的中间件。

所以,让我们开始吧。

什么是Redux中间件?

Redux中间件允许你拦截发送到还原器的每个动作,这样你就可以对动作进行修改或取消动作。

中间件可以帮助你记录、报告错误、进行异步请求,以及更多。

看一下下面的代码吧:

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中创建中间件

要创建一个中间件,我们首先需要像这样从Redux导入applyMiddleware 函数:

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);
};

这里是上述代码沙盒演示的预览链接

如果你检查控制台,你会看到以下输出:

在动作被派发到商店之前,中间件被执行,因为我们可以看到动作被记录到控制台。因为我们在loggerMiddleware 里面通过传递动作来调用next 函数,所以reducer也会被执行,从而导致商店里的变化。

现在,如果我们不在loggerMiddleware 内调用next 函数,会发生什么?

,那么动作将不会被发送到reducer,所以商店将不会被更新。

如果你使用过Node.js,那么你可能会发现这与中间件在Node.js中的工作方式类似。

在Node.js的中间件中,如果我们不调用下一个函数,请求将不会被向前发送。

这里有一个更新的代码沙盒演示,其中删除了下一个 函数的调用:

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

这里是上述代码沙盒演示的预览链接

如果你检查控制台,你会看到以下输出:

正如你所看到的,我们只得到记录在控制台的动作。而由于动作没有被转发到reducer,它将不会被执行--所以我们看不到来自store.subscribe 函数的console.log

正如前面所描述的,我们可以在动作被发送到还原器之前从中间件中修改动作。

下面是一个更新的代码沙盒演示,我们正在改变动作的有效载荷,然后再发送到还原器。

中间件的代码看起来像这样:

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

这里是上述代码沙盒演示的预览链接:

按照代码,一旦动作被记录到控制台,我们就会将动作的有效载荷设置为3的值。所以动作type ,但payload

所以我们看到最初的状态变成了3。然后再次增加3,使之成为6。最后,它被减去3,使得最终的状态值为3。

在动作被发送到还原器之前,我们的loggerMiddleware 被调用,在那里我们改变了有效载荷的值,在它被发送到还原器之前我们总是将它设置为3。因此,基于动作类型INCREMENT或DECREMENT,还原器将总是被改变3的值。

即使我们在上面的代码中改变动作,在这种情况下也没有问题,因为它是一个中间件而不是一个还原器。

在上面的代码例子中,我们已经创建了一个单一的中间件。但你可以创建多个中间件,并像这样把它们传递给applyMiddleware 函数:

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

applyMiddleware 函数中提到的所有中间件将被一个接一个地执行。

谢谢你的阅读!