前言:该文章主要讲解如何在 react
项目中接入 redux
数据状态管理,假设你已经阅读过这篇文章中的前半篇(除去添加数据管理这一段)。
- 安装需要的依赖包
npm install redux react-redux --save
-
新建需要的文件夹
在src
目录下新建actions
、reducers
、constants
文件夹,actions
存放分发的action
函数;reducers
存放单个的reducer
;constants
存放分发action
的type
常量。在
reducers
中创建index.js
,用来组合单个的reducer
,输出根state
import { combineReducers } from 'redux'
export default combineReducers({})
- 修改
webpack
文件来设置别名
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>
)
现在你可以编写你自己的 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
,执行后也需要返回一个 action
;如果需要执行下一步,调用 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)),
)
当然还是附上项目地址
欢迎指正、star
中途遇到的问题
1.reducer
- 控制台提示
No reducer provided for key 'xxxReducer'
出现情况: 两个reducer文件如下写
const reducer = () => {};
export default reducer;
在reducer汇总文件分别使用
export default combineReducers({
reducer1,
reducer2,
});
这种写法会出现No reducer provided for key 'xxxReducer'
解决方法:
- 让每个reducer命名不重复
const reducer1 = () => {};
export default reducer1;
- 直接这样导出
export default () => {}
redux不更新数据问题
问题: 在 component
中直接对 state
树的值进行修改,将修改后的数据 action
到 reducer
中,结果 reducer
的数据更新了,但是页面并没有重新渲染
原因: redux
的 state
是引用,直接对 state
的值进行更改时,store
内部的 state
值同样也改变了,这样导致 redux
认为 dispatch
前后 state
没有改变,就不会重新渲染UI,实际上 state
已经改变了