Why redux-actions?
最近一直在Redux卡關, 除了有點玄妙的邏輯以外, 更重要的是他的boilerplate code很繁瑣, 於是在Telegram群組的大大推薦下, 我使用了Redux-Actions的插件, 效果差了很多! 人生也變得美好XD 在這邊我講記錄我更改的過程.
背景提要:
我要在我的程式用HTML 5的Api取得使用者的座標, 再來更新使用者位置的天氣, 當中會用到兩個api, 在這邊我其實會有點疑問: 到底HTML5 GeoLocation的取得, 是不是Async的呢? 不過我不管啦, 先設定成是Async的好了, 那在這個範例就是有兩個Async的動作.(目前進度的關係, 先只有用到座標Api)
正常來說在傳統的React-Redux應該是這個樣子:
詳細的Code請點我
weather-actions.js
1 | import { getUserLocation as getUserLocationFromApi } from 'component/userLocation.jsx'; |
weather-reducer.js
1 | const initLocationState = { |
createAction
這個是原本的code, 但是用上redux-actions之後code變成這樣:
Before:
1 | function startGetUserLocation() { |
After:
1 | import { createAction } from 'redux-actions'; |
handleActions
Before:
1 | const initLocationState = { |
After:
1 | import { handleActions, combineActions } from 'redux-actions'; |
Spread and Destructuring
但是我覺得action.payload.lat, action.payload.lng, res.coords.latitude很繁冗, 後來我利用了spread和解構的語法, 讓他看起來比較整潔:
Before:
1 | export const location = handleActions({ |
After:
1 | export const location = handleActions({ |
combineActions:
再來我覺得原本handleActions那邊有點冗,
Before:
1 | export const location = handleActions({ |
配合 Redux Actions 的 combineActions:
After:1
2
3
4
5export const location = handleActions({
[combineActions('GET_LOCATION', 'GET_LOCATION_STATUS')](state, action) {
return { ...state, ...action.payload}
}
}, initLocationState);
combineActions的小坑:
在官方的Api文檔範例中, 他使用的是return { …state, counter: state.counter + amount }; 讓人會誤以為, 只能單純為計算才能combineActions(還是只有我這樣覺得?). 而我發現只要在dispatch的時候, 用object({})的方式傳到reducer, 再把傳入的object使用spread action.payload, 他就會根據你之前的設定好的initState, 找出相應的key來覆蓋. 但是這邊有點問題: combineAction裡面的args會越來越多,變得超級無敵長, 真的很可怕, 除了多寫幾個handle actions來分隔以外, 還有其他方法嗎?
20180401 combineActions的理解錯誤
使用了以上的方法一段時間后,發現我什麽都能dispatch,甚至lat、lng的欄位,都能dispatch boolean值(預設值是數字),讓我維護變得更麻煩,更加難除錯。我發現了一個人,他寫了關於一系列相當清楚的教學,他不建議使用combineActions,畢竟很多時候每一個action都有自己的目的(不用到的幹嘛不簡化成一個XD),因此在某種程度上,combineActions是不被需要的。
下面將會新增利用這樣的概念寫好的code:
結論
簡單來說, Redux-Actions他簡化了一些模板code, 比方說action不用每一個都寫function, reducers不用寫switch case, 這樣的確少了很多麻煩. 今天的經驗分享就到這邊!
完整code
*20180401新增:
新版本的示範凑得請點我
todo-reducers.js
1 | const initTodoState = { |
todo-actions.js
1 | import { createAction, createActions } from 'redux-actions'; |
完整的code請點我
weather-reducers.js
1 | import { handleActions, combineActions } from 'redux-actions'; |
weather-actions.js
1 | import { getUserLocation as getUserLocationFromApi } from 'component/userLocation.jsx'; |
參考資料
- https://github.com/dc198689/orange/blob/master/src/actions/posts/getPosts.js
- https://github.com/ecmadao/Coding-Guide/blob/master/Notes/React/Redux/%E4%BD%BF%E7%94%A8%20Redux%20%E6%89%93%E9%80%A0%E4%BD%A0%E7%9A%84%E5%BA%94%E7%94%A8%20%E2%80%94%E2%80%94%20redux-actions.md
- https://redux-actions.js.org/docs/introduction/Tutorial.html
- https://ithelp.ithome.com.tw/articles/10187009
- https://www.jianshu.com/p/6ba5cd795077