PJCHENder 未整理筆記

[Redux] Redux Middleware

2018-09-20

[Redux] Redux Middleware

@(React)[React, Redux]

Middleware 是在 action 進入到 reducer 之前,可以讓我們做一些介入 action 的時間點:

透過 Middleware 我們可以延遲、記錄(log)、調整或停止 action

在 Redux 中並沒有限制 Middleware 的數量,因此我們可以有很多個 middleware,每個 middleware 會檢查這是不是自己需要處理的 action,如果不是就會傳給下一個 middleware 繼續處理。

打造 Redux Promise Middleware

Redux Promise Middleware,會在 action 進來的時候判斷這個 action 是不是包含有 Promise 物件,如果沒有的話會直接傳遞到進到下一個 middleware;如果有 Promise 物件的話,則會進入這個 middleware,這個 middleware 會等到 Promise resolvereject 之後,會把 payload 帶有 Promise 的結果後,重新發送一個新的 action,這個 action 會從頭開始,再次經過所有的 middleware,但因為這次它已經不帶有 Promise 物件,因此會直接被傳遞到下一個 middleware。

:exclamation: 當 Redux Promise Middleware 等到 Promise resolve 或 reject 之後,是會發送一個新的 action,這個 action 會從第一個 middleware 重新走起,而不是把處理完的資料直接丟到 reducers

boilerplate

Middleware 的樣版長的像這樣:

1
2
3
4
5
6
7
8
9
10
11
12
13
// ./middlwares/async.js

// 簡化後的寫法:
export default ({ dispatch }) => next => action => { ... }

// 完整的寫法如下:
// export default function({ dispatch }) {
// return function(next) {
// return function(action) {

// };
// };
// }

Sample Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// ./middlwares/async.js

export default ({dispatch}) => next => action => {
// 檢查看看 action 的 payload 屬性是否是 Promise 物件

// 如果不是 Promise 物件(用 then 檢查),那麼將 action 傳送到下一個 middleware
if (!action.payload || !action.payload.then) {
// return 並不是必要的,但可以確保 return 之後的程式碼不會被執行到
return next(action);
}

// 如果是的話,等待 Promise 被 resolved,
// 然後建立一個帶有 resolved 資料的新 action,並發送(dispatch)它
action.payload.then(response => {
const newAction = { ...action, payload: response };
dispatch(newAction);
}).catch(error => {
const newAction = { ...action, payload: error };
dispatch(newAction);
})
}

放入 Middleware 到 Redux 中

1
2
3
4
5
6
7
8
9
10
import { createStore, applyMiddleware, composeEnhancers } from 'redux';

// 有使用 Redux Devtools
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(rootReducers, composeEnhancers(
applyMiddleware(asyncMiddleware)
));

// 不使用 Redux Devtools
const store = createStore(rootReducers, applyMiddleware(asyncMiddleware));
Tags: Redux

掃描二維條碼,分享此文章