前言:該文章主要講解如何在 react 項目中接入 redux 數(shù)據(jù)狀態(tài)管理,假設(shè)你已經(jīng)閱讀過這篇文章中的前半篇(除去添加數(shù)據(jù)管理這一段)。
- 安裝需要的依賴包
npm install redux react-redux --save
-
新建需要的文件夾
在src目錄下新建actions、reducers、constants文件夾,actions存放分發(fā)的action函數(shù);reducers存放單個的reducer;constants存放分發(fā)action的type常量。在
reducers中創(chuàng)建index.js,用來組合單個的reducer,輸出根state
import { combineReducers } from 'redux'
export default combineReducers({})
- 修改
webpack文件來設(shè)置別名
alias: {
styles: paths.appStyles,
routes: paths.appRoutes,
components: paths.appComponents,
actions: paths.appActions,
constants: paths.appConstants,
reducers: paths.appReducers,
...
- 添加
redux-thunk異步中間件
npm install redux-thunk --save
- 修改
routes文件夾下的index.js
...
import { Provider } from 'react-redux'
import { createStore, applyMiddleware, compose } from 'redux'
import thunkMiddleware from 'redux-thunk'
import rootReducer from 'reducers'
...
const store = createStore(
rootReducer,
compose(applyMiddleware(thunkMiddleware)),
)
const App = () => (
<Provider store={store}>
<Routes />
</Provider>
)
現(xiàn)在你可以編寫你自己的 action,reducer 了。
- 配合瀏覽器安裝輔助工具
Redux DevTools
Chrome瀏覽器安裝Redux DevTools擴展程序,修改routes中的index.js
let composeEnhancers = compose
if (process.env.NODE_ENV === 'development') {
composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; // eslint-disable-line
}
const store = createStore(
rootReducer,
composeEnhancers(applyMiddleware(thunkMiddleware)),
)
在瀏覽器界面打開 Redux DevTools 就能看見以下效果

編寫middleware
如果需要自定義的 middleware,很簡單,這個 middleware 只接收一個 action,執(zhí)行后也需要返回一個 action;如果需要執(zhí)行下一步,調(diào)用 next(action) 即可。
- 日志的中間件
const logger = store => next => (action) => {
console.log('dispatching', action);
const result = next(action);
console.log('next state', store.getState());
return result;
};
修改 routes文件夾下的 index.js,將該日志中間件加上
const store = createStore(
rootReducer,
composeEnhancers(applyMiddleware(thunkMiddleware, logger)),
)
當(dāng)然還是附上項目地址
歡迎指正、star
中途遇到的問題
1.reducer
- 控制臺提示
No reducer provided for key 'xxxReducer'
出現(xiàn)情況: 兩個reducer文件如下寫
const reducer = () => {};
export default reducer;
在reducer匯總文件分別使用
export default combineReducers({
reducer1,
reducer2,
});
這種寫法會出現(xiàn)No reducer provided for key 'xxxReducer'
解決方法:
- 讓每個reducer命名不重復(fù)
const reducer1 = () => {};
export default reducer1;
- 直接這樣導(dǎo)出
export default () => {}
redux不更新數(shù)據(jù)問題
問題: 在 component 中直接對 state 樹的值進行修改,將修改后的數(shù)據(jù) action 到 reducer中,結(jié)果 reducer 的數(shù)據(jù)更新了,但是頁面并沒有重新渲染
原因: redux 的 state 是引用,直接對 state 的值進行更改時,store 內(nèi)部的 state 值同樣也改變了,這樣導(dǎo)致 redux 認(rèn)為 dispatch 前后 state 沒有改變,就不會重新渲染UI,實際上 state 已經(jīng)改變了