npm i redux 使用redux创建仓库
npm i react-redux
npm i redux-thunk 使用异步action
npm i redux-inmutable 进行合并reducer优化
redux-devtools 1.安装插件 2.代码内进行配置 可在GitHub的redux-devtools进行配置参考
- store/ index.js
// applyMiddleware(应用中间件) 接收项目需使用的中间件作为参数
import { createStore, applyMiddleware, compose } from 'redux';
// 使用异步action的中间件
import thunkMiddleware from 'redux-thunk';
import reducer from './reducer/index';
// 安装redux-devtools插件会在window 添加环境变量, 否则使用 compose 才可以进行查看调试
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({trace: true}) || compose;
const storeEnhancer = applyMiddleware(thunkMiddleware);
const store = createStore(reducer, composeEnhancers(storeEnhancer));
export default store;
- store/actions.js 文件
import { CHANGE_RECOMMEND } from './constantsType'
const createAction = (type, payload) => ({type, payload})
// 同步action为对象
export const changeRecommend = (data) => createAction(CHANGE_RECOMMEND,data);
// 异步action为函数 传参则再包裹一层接收参数 redux-thunk中定义的action函数
export const getHomeMultidataAction = (params) => async (dispatch, getState) => {
const { data } = await getRewardList({...params})
dispatch(changeRecommend(data));
}
- store/constantsType.js
export const CHANGE_RECOMMEND = "CHANGE_RECOMMEND";
- store/reducer/rewardReducer.js
import { CHANGE_RECOMMEND } from './constants.js';
import { Map } from 'inmutable'
const defaultState = {
reward: []
}
const rewardReducer = (state = defaultState, action) => {
const { type, payload } = action
switch (type) {
case CHANGE_RECOMMEND:
return { ...state, reward: payload };
default:
return state;
}
}
export default rewardReducer;
- reducer/index.jsx
import rewardReducer from './rewardReducer';
import homeReducer from './home';
// import { combineReducers } from 'redux';
import { combineReducers } from 'redux-inmutable';
// 合并多个reducer
const reducer = combineReducers({
rewardReducer,
homeReducer
});
export default reducer;
- 最外层 index.js
import React from 'react';
import ReactDOM from 'react-dom';
import store from './store';
import { Provider } from 'react-redux';
import App from './App';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
- ui类组件内使用
import React, { PureComponent } from 'react';
import { connect } from 'react-redux';
import { getHomeMultidataAction } from '../store/actionCreators'
class Home extends PureComponent {
componentDidMount() {
this.props.getHomeMultidata();
}
render() {
return <h2>当前计数: {this.props.counter}</h2>
}
}
const mapStateToProps = state => ({
counter: state.counter
})
const mapDispatchToProps = dispatch => ({
getHomeMultidata() {
dispatch(getHomeMultidataAction);
}
})
// connect 内部会对每次 return 的 {} 与上一次进行浅层比较
// 当前组件内引用的state没有发生变化, 其他组件修改state时, 则不会重新渲染组件(不影响当前组件)
export default connect(mapStateToProps, mapDispatchToProps)(Home);
- ui hooks组件内使用
// shallowEqual 进行state是否变化的浅层比较
import { useDispatch, useSelector, shallowEqual } from 'react'
const RewardCenter = () => {
const { reward } = useSelector(state => ({
reward: state.rewardReducer.reward,
// reward: state.get("rewardReducer").get("reward") 使用inmutable后的取值
// reward: state.getIn(["rewardReducer", "reward"])
}), shallowEqual)
const dispatch = useDispatch()
return <h2>当前计数: {counter}</h2>
}