Redux - 中间件
Redux 本身是同步的,那么像网络请求这样的异步操作如何在 Redux 中工作?这里中间件就派上用场了。如前所述,reducers 是编写所有执行逻辑的地方。Reducer 与谁执行它、花费多少时间或记录操作分派前后应用程序的状态无关。
在这种情况下,Redux 中间件函数提供了一种在分派的操作到达 reducer 之前与其交互的方法。可以通过编写高阶函数(返回另一个函数的函数)来创建自定义中间件函数,该函数围绕某些逻辑进行包装。可以将多个中间件组合在一起以添加新功能,并且每个中间件都不需要了解之前和之后发生了什么。您可以将中间件想象成操作分派和 reducer 之间的东西。
通常,中间件用于处理应用程序中的异步操作。Redux 提供了一个名为 applyMiddleware 的 API,它允许我们使用自定义中间件以及 Redux 中间件(如 redux-thunk 和 redux-promise)。它将中间件应用于 store。使用 applyMiddleware API 的语法如下:
applyMiddleware(...middleware)
这可以应用于 store,如下所示:
import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import rootReducer from './reducers/index'; const store = createStore(rootReducer, applyMiddleware(thunk));
中间件将允许您编写一个操作分派器,它返回一个函数而不是一个操作对象。下面显示了相同内容的示例:
function getUser() { return function() { return axios.get('/get_user_details'); }; }
可以在中间件内编写条件分派。每个中间件都接收 store 的 dispatch,以便它们可以分派新的操作,并将 getState 函数作为参数,以便它们可以访问当前状态并返回一个函数。内部函数的任何返回值都将作为 dispatch 函数本身的值可用。
以下是中间件的语法:
({ getState, dispatch }) => next => action
getState 函数用于确定是否要获取新数据或返回缓存结果,具体取决于当前状态。
让我们来看一个自定义中间件日志记录函数的示例。它只是记录操作和新状态。
import { createStore, applyMiddleware } from 'redux' import userLogin from './reducers' function logger({ getState }) { return next => action => { console.log(‘action’, action); const returnVal = next(action); console.log('state when action is dispatched', getState()); return returnVal; } }
现在通过编写以下代码行将日志记录中间件应用于 store:
const store = createStore(userLogin , initialState=[ ] , applyMiddleware(logger));
使用以下代码分派一个操作以检查分派的操作和新状态:
store.dispatch({ type: 'ITEMS_REQUEST', isLoading: true })
下面是另一个中间件示例,您可以在其中处理何时显示或隐藏加载程序。此中间件在您请求任何资源时显示加载程序,并在资源请求完成后隐藏它。
import isPromise from 'is-promise'; function loaderHandler({ dispatch }) { return next => action => { if (isPromise(action)) { dispatch({ type: 'SHOW_LOADER' }); action .then(() => dispatch({ type: 'HIDE_LOADER' })) .catch(() => dispatch({ type: 'HIDE_LOADER' })); } return next(action); }; } const store = createStore( userLogin , initialState = [ ] , applyMiddleware(loaderHandler) );