阅读 redux 源码的时候,发现 redux 给我们提供了一系列方法。
- createStore ( redux 创建 store; 必备 )
- applyMiddleware ( redux 注入中间件 )
- compose ( redux 组合多个中间件)
下面这两个方法是干啥用的呢?
- bindActionCreators
- combineReducers
1. 定义 action 文件
一个文件定义多个 action 方法,一般跟某一个业务相关的 action 放在同一个文件中。
//action.js
export const Action1 = () => {
return { type: "action", payload: "Action1" };
};
export const Action2 = () => {
return (dispatch) => {
dispatch({ type: "action", payload: "Action2" });
};
};
export const Action3 = () => {
return { type: "action", payload: "Action3" };
};
...
2. 一般的action绑定方式
// App.jsx
import * as actions from "./action";
export default connect(
(state) => state,
(dispatch) => {
//返回一个 action 集合对象
return {
Action1: () => dispatch(actions.Action1()),
Action2: () => dispatch(actions.Action2()),
Action3: () => dispatch(actions.Action3()),
...
};
}
)(App);
一般 action 比较少的时候用这种方式绑定还能接受。如果对于复杂的项目,一个业务需要绑定的 action 超过10个甚至更多,还用这种罗列式绑定不仅代码重复而且繁重。
图片可以看出 react-redux 将 action 成功的绑定到了 props 属性上。
3. bindActionCreators 使用
// App.jsx
import { bindActionCreators } from "redux";
import * as actions from "./action";
export default connect(
(state) => state,
(dispatch) => {
return {
...bindActionCreators(actions, dispatch),
};
}
)(App);
使用 bindActionCreators 绑定 action 一行代码就搞定。
有的人不喜欢把 action 方法直接放在 props 第一层,那么我再套一层就好了
// App.jsx
import { bindActionCreators } from "redux";
import * as actions from "./action";
...
export default connect(
(state) => state,
(dispatch) => {
return {
actions: bindActionCreators(actions, dispatch),
};
}
)(App);
connect 方法会把方法返回的对象绑定到 props 上,那么只要我搞定,我可以无线套娃。
export default connect(
(state) => state,
(dispatch) => {
// 返回的内容直接绑定到 props
return {
//无线套娃
action1: {
action2: bindActionCreators(actions, dispatch),
},
};
}
)(App);
**但是 bindActionCreators 只能处理一层actions对象(通过源码分析),但是很多时候我们需要把多个 action 方法集中到同一个 actions.js 文件,这个时候用 bindActionCreators 处理绑定 action,就只会处理第一层 **
举例说明
export const commonAction1 = () => {
return { type: 'xxx' };
};
export const commonAction2 = () => {
return { type: 'xxx' };
};
import { commonAction1, commonAction2 } from './commonAction';
export const actions = {
//引入公共模块 action
commonAction1,
commonAction2,
Action1: () => {
return { type: 'xxx' };
},
Action2: () => {
return { type: 'xxx' };
},
Action3: () => {
return { type: 'xxx' };
},
};
直接用 bindActionCreators 方法处理 action 不能绑定成功
自定义方法递归处理 action
// bindActionCreatorsPlus.js
import { bindActionCreators } from 'redux';
export default function bindActionCreatorsPlus(actions, dispatch) {
if (typeof actions !== 'object' || !actions) {
throw new Error('invalid actions');
}
let result = {};
for (let key in actions) {
if (actions.hasOwnProperty(key)) {
const creator = actions[key];
if (typeof creator === 'object' && creator) {
//递归执行
result[key] = bindActionCreatorsPlus(creator, dispatch);
} else if (typeof creator === 'function') {
result[key] = bindActionCreators(creator, dispatch);
}
}
}
return result;
}
import React from 'react';
//引入 bindActionCreatorsPlus.js
import bindActionCreatorsPlus from './bindActionCreatorsPlus';
import { connect } from 'react-redux';
import * as actions from './action';
const Application = (props) => {
console.log(props);
return ;
};
export default connect(
(state) => state,
(dispatch) => {
return {
action: bindActionCreatorsPlus(actions, dispatch),
};
},
)(Application);
绑定成功,如此不管嵌套几层,都可以把 action 方法绑定到 props
createStore 方法创建新 store 需要传入一个 reducer 方法 。但是复杂的业务需要把 reducer 区分开,但是 createStore 只能接受一个 reducer。 需要把多个 reducer 合并成同一个,combineReducers 方法就是为了合并 reducer。
import { createStore, combineReducers } from "redux";
// 此处偷懒,把多个 reducer放在一起了
//第一个 reducer
const oneReducer = (state = {}, action) => {
switch (action.type) {
case "action":
return { ...state, actions: action.payload };
case "levenx":
return { ...state, AB: action.payload };
default:
return state;
}
};
// 第二个 reducer
const twoReducer = (state = {}, action) => {
switch (action.type) {
case "action":
return { ...state, actions: action.payload };
case "levenx":
return { ...state, AB: action.payload };
default:
return state;
}
};
.... // N 个reducer
const reducer = combineReducers({
one: oneReducer,
two: twoReducer });
// 创建 store 实例
const store = createStore(reducer, {});
export { store };