用Redux Thunk 來處理非同步action
Redux Thunk的目的就是為了實踐middleware,讓action能做更多的事,想必大家都曾經看過這個錯誤,當action為非同步的時候,就會報錯,Redux Thunk就是為了解決這個問題而生
來看一下Redux Thunk的原始碼
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
你沒看錯,就只有這樣。
原本的action creator 都是回傳action object,在Redux Thunk裡面會檢查若action不是object而是function,就會執行function後再將action往下傳,直到回傳object才會進去reducers
那麼接著來實作一下,情境很簡單,call api拿到資料後dispatch更新資料,讓畫面依據資料長出列表
記得要先安裝
npm install redux-thunk --save
store的部分因為比之前複雜,就從index.js抽離出來獨立
createStore可以接受三個參數(reducer、初始state、applyMiddleware),而applyMiddleware又可以傳入三個參數(thunk、promise、logger
順帶一提,我有另外安裝redux-logger,會在action觸發和state變化時自動印出log,個人覺得在除錯方面還蠻方便的
index.js 將store傳入
這邊為了簡單做個練習,所以只寫了一個action,處理資料接收,fetchPosts在拿到api資料後dispatch receivePosts(json.data),可以發現fetchPosts是回傳一個函式
getBikeList 可以同時拿到getState和dispatch方法
reducersBike.js
經過Middleware處理後,最後將資料傳給reducer,改變state之後重新渲染UI畫面
一切準備就緒之後,在componentDidMount階段dispatch getBikeList,在還沒拿到資料等待api回應之前先顯示loading,(本來是要接高雄Youbike據點的api,但api時好時壞,只好改接市場資料orz
下面這部分就跟以往的redux一樣
最後成功拿到列表!
除了react-thunk之外,再處理Middleware非同步這塊,Redux Saga也會是個不錯的選擇,日後有機會再來分析兩者的差異。