使用包含自定义功能的 middleware 来扩展 Redux 是一种推荐的方式。Middleware 可以让你包装 store 的dispatch 方法来达到你想要的目的。同时, middleware 还拥有“可组合”这一关键特性。多个 middleware 可以被组合到一起使用,形成 middleware 链。其中,每个 middleware 都不需要关心链中它前后的 middleware 的任何信息。
Middleware 最常见的使用场景是无需引用大量代码或依赖类似 Rx 的第三方库实现异步 actions。这种方式可以让你像 dispatch 一般的 actions 那样 dispatch 异步 actions。
例如,redux-thunk 支持 dispatch function,以此让 action creator 控制反转。被 dispatch 的 function 会接收 dispatch 作为参数,并且可以异步调用它。这类的 function 就称为 thunk。另一个 middleware 的示例是 redux-promise。它支持 dispatch 一个异步的 Promise action,并且在 Promise resolve 后可以 dispatch 一个普通的 action。
Middleware 并不需要和 createStore 绑在一起使用,也不是 Redux 架构的基础组成部分,但它带来的益处让我们认为有必要在 Redux 核心中包含对它的支持。因此,虽然不同的 middleware 可能在易用性和用法上有所不同,它仍被作为扩展 dispatch 的唯一标准的方式。
参数
-
...middlewares(arguments): 遵循 Redux middleware API 的函数。每个 middleware 接受Store的dispatch和getState函数作为命名参数,并返回一个函数。该函数会被传入 被称为next的下一个 middleware 的 dispatch 方法,并返回一个接收 action 的新函数,这个函数可以直接调用next(action),或者在其他需要的时刻调用,甚至根本不去调用它。调用链中最后一个 middleware 会接受真实的 store 的dispatch方法作为next参数,并借此结束调用链。所以,middleware 的函数签名是({ getState, dispatch }) => next => action。
返回值
(Function) 一个应用了 middleware 后的 store enhancer。这个 store enhancer 就是一个函数,并且需要应用到 createStore。它会返回一个应用了 middleware 的新的 createStore。
示例: 自定义 Logger Middleware
1 import { createStore, applyMiddleware } from 'redux' 2 import todos from './reducers' 3 4 function logger({ getState }) { 5 return (next) => (action) => { 6 console.log('will dispatch', action) 7 8 // 调用 middleware 链中下一个 middleware 的 dispatch。 9 let returnValue = next(action) 10 11 console.log('state after dispatch', getState()) 12 13 // 一般会是 action 本身,除非 14 // 后面的 middleware 修改了它。 15 return returnValue 16 } 17 } 18 19 let createStoreWithMiddleware = applyMiddleware(logger)(createStore) 20 let store = createStoreWithMiddleware(todos, [ 'Use Redux' ]) 21 22 store.dispatch({ 23 type: 'ADD_TODO', 24 text: 'Understand the middleware' 25 }) 26 // (将打印如下信息:) 27 // will dispatch: { type: 'ADD_TODO', text: 'Understand the middleware' } 28 // state after dispatch: [ 'Use Redux', 'Understand the middleware' ]