[Redux] Redux Thunk
- What the heck is a 'thunk'?
- redux-thunk @ Github
- Writing Logic with Thunks @ Redux > Using Redux > Redux Logic and Patterns
TL;DR
- 從原始碼中可以知道,redux-thunk 真的只是用來讓開發者能夠在 redux 中呼叫非同步請求,但它沒有除了其他 API 請求時需要處理的問題(例如,dedupe、race condition、發出請求和得到結果的順序)
thunk
是一個 function 讓我們能夠處理 async 的操作,thunk function 是能接受 dispatch 和 getState 作為參數的函式,用來產生 think function 的函式則稱作thunk creator
:
// const thunkCreator = () => (dispatch, getState) => {...}
// const thunkFunction = (dispatch, getState) => {...}
// incrementAsync 是 thunkCreate,執行後會回傳 thunk function
export const incrementAsync =
(amount: number): AppThunk =>
(dispatch, getState) => {
setTimeout(() => {
dispatch(incrementByAmount(amount));
}, 1000);
};
// 使用 thunk function
store.dispatch(incrementAsync(5));
備註
從原本的英文來說,thunk
單純是指一個函式回傳了另一個函式時,那個「被回傳出來的函式」(What the heck is a 'thunk'?)。
Redux Thunk middleware 讓你可以撰寫一個回傳 function 而非 action 的 action creators,透過 thunk 可以讓你控制發送(dispatch)一個 action 的時間點,因此適合用來處理非同步取得的資料狀態,或者是在特定條件符合的情況下才發送。
使用
使用 redux-thunk 時,action creators 會回傳的不是物件,而是一個帶有 dispatch
, getState
, extraArgument
參數的 async function,並在這個 async function 會再去執行 dispatch
方法,來通知到 reducer:
export const FETCH_USERS = 'fetch_users';
export const fetchUsers = () => async (dispatch, getState, axiosInstance) => {
const res = await axiosInstance.get('/users');
dispatch({
type: FETCH_USERS,
payload: res,
});
};
async function 執行後 本身也是一個 Promise,可以透過
.then()
繼續串接。
Source Code
function createThunkMiddleware(extraArgument) {
// 這是 middleware 基本的寫法
return ({ dispatch, getState }) =>
(next) =>
(action) => {
// action 就是透過 action creators 傳進來的東西,
// 在 redux-thunk 中會是 async function
if (typeof action === 'function') {
// 在這裡回傳「執行後的 async function」
return action(dispatch, getState, extraArgument);
}
// 如果傳進來的 action 不是 function,則當成一般的 action 處理
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;