前言
最典型的一個react項目就是react-router+redux(可能再加上redux-thunk或saga),在hooks出來之后,redux也同步跟進加了很多hooks,但已經可以完全拋棄redux,僅僅使用useReducer等hooks來管理數據流了(大型、復雜項目的話,目前還是推薦redux)
這個版本的代碼在這
步驟
前文中已經配置好webpack了,接下來讓我們配置react-router以及reducer
react-router
先安裝依賴:
npm i -S react-router-dom react-helmet
react-router-dom是基於react-router的庫,里面加入了一些在瀏覽器運行環境下的功能,例如:Link、BrowserRouter、HashRouter。而其他的一些組件則是直接從react-router中導出的,例如:Switch、Route等等。
react-helmet用來動態改變title
路由及布局
路由及布局,就跟我們平時寫的react應用是一樣的,先寫個最簡單的就行,就不詳細展開了,具體看代碼即可,主要新增了3個文件:
- routes.js 定義路由
- layout 定義布局
- RouteWithSubRoutes react-router的嵌套路由組件
插曲
寫了幾個基礎頁面后,發現報這種錯:
Module not found: Error: Can't resolve 'core-js/modules/es.array.slice'
看了一下package.json,果然,遺漏安裝core-js了,因為@babel/preset-env依賴core-js,會跑到當前項目下去尋找core-js
因為用到的是core-js3,所以我們安裝core-js3:
npm i core-js@3
redux
接下來就是全局狀態管理,以往我們都是用redux及react-redux,不過在有了useReducer和useContext之后,已經可以替代了
在hooks之前createContext配合Context.Consumer也能讀取全局狀態,只不過很不方便,這篇文章講的不錯
簡單來說,使用useReducer和useContext來接管redux,主要有3步,示例代碼如下:
-
createContext創建一個全局context
js const Store = createContext(initState);
-
使用上一步的context,導出Provider組件,value中傳入useReducer的state及dispatch
const [state, dispatch] = useReducer(reducer, initState);
return <Store.Provider value={{state, dispatch}}>
</Store.Provider>
接下來就是傳統的寫法了,dispatch(action()),顯然每個頁面都這么寫的話,還是挺繁瑣的
如果能像vue那樣mapAction,直接調用action,那就方便多了
redux4中有一個bindActionCreators,跟mapAction作用類似傳入action和dispatch,返回一個直接調用的action
而且代碼多了之后,肯定是需要拆分reducer及action的,所以我們可以這樣進行拆分:
- 建一個reducers文件夾
- 一個業務對應一個reducer文件,每個文件里定義actions、reducers
- 新增一個builder文件,遍歷處理,將actions用dispatch包一層,reducers則簡單合並,最后導出新的actions、一個新的root reducer
結構如下:
- redux
- reducers
- global.ts
- todo.ts
- index.ts
- builder.ts
- store.tsx
- 創建一個useRedux hooks,快捷使用state、dispatch
const {state, dispatch, actions} = useContext(Store);
更具體的代碼就不一行行展示了,在tag-v2中可以詳細查看
小結
可以看到,createContext+useContext+useReducer這3個react內置的api,已經足夠應對小型項目的全局狀態管理了