Redux 異步 Action 解決一式 (Thunk 法)

miZyind
miZyind Singularity
5 min readAug 9, 2018

--

前情提要

在 Redux 的機制下
資料更新流程都已明確拆分為 action, reducer, store 的相互搭配了

每當資料需要被更新,我們就會呼叫 dispatch 調用特定 action
再藉由 Redux 的機制找出對應 reducer,接著交由它來更新 store

本文範例假設 component 已經經過 connect 處理變為 container
可以直接在 props 中調用該 action 並自動 dispatch
因此程式碼就不會再出現 store 了
(如果看到這段覺得黑人問號,可以參考 react-redux connect api)

這個看似簡單的流程,在初次面對非同步資料處理時可能會稍微亂了套
因此透過本文簡單紀錄一下我的想法以及解決方式
但 Thunk 不是一個最佳解法,寫起來畢竟還是有些不自然
不過它算是最清楚易懂且學習門檻低的做法了!

來個小範例

假如我們有個用來新增多筆產品的 action 稱為 addProducts
實作 action-creator:

同時也有一個用來管理產品的 component
我希望在它被建構時就先放入一些範例產品至 store 中
實作起來大概會長這樣:

如此一來這個 mockProducts 即會經過 Redux 機制
清楚明瞭又順利地更新我們的 store
當然這個地方我省略了 reducer 實作部份,就不多解釋

遇到麻煩了

然而當我們的 addProducts 需要從 server 取得真實資料時怎麼辦?
這時 component 可能會長成:

雖然上面的寫法一樣能達成我們的需求取得資料,但就是看不順眼!
不僅 component 內多了些複雜邏輯
我們要在別的 component 做一樣事情時,又得重複一次這段程式碼
讓我想到前輩的一句話:「Do not repeat yourself!」

Jesse we have to CODE!

從 server 取資料總會有失敗的可能
且為了讓使用者感受更好,我們可能也要增加一些 loading 效果
既然一個 action 吃不夠,就吃兩個 action 吧!

這時候 thunk 就能介入了!

接著 component 也能改寫為:

如此一來就完成非同步 action 的改寫了
程式碼不僅變得簡潔,其他地方需要調用同樣 action 時也不用整個重複寫!

奇怪?store.dispatch 竟然可以傳 function 進去!?

如果有注意到這點,表示你骨骼驚奇,必是練武奇才啊!
馬上來看最初 action 的寫法是怎麼被調用的:

可以看到 store.dispatch 最後拿到的參數型別會是個「object」!
再看看改寫後的怎麼被調用:

上面程式碼的第 3 行傳的明明是「function」
怎麼可以被 dispatch 而不出錯呢?
如果沒有 redux-thunk 這個 middleware 的介入其實是辦不到這件事的
經過 middleware 的處理:

可以看到它會先判斷 action 是否為一個 function
若是的話就直接呼叫 action,並把相關參數傳遞進去
執行起來就會是以下正常又自然的流程啦:

如何套用 middleware 至 Redux?

使用 redux-thunk 文件中的範例即可輕鬆套用:

假如已經有套用例如 Redux Devtool 的 Enhancer 後怎麼辦呢?
使用方法如下:

如此一來就能好好享受 redux-thunk 帶來的好處啦!

--

--