dispatch 即可以是提交一个对象的语法, 还可以提交一个函数的写法
直接通过提交函数派发动作
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { createStore, bindActionCreators } from './redux';
let initData = {
num: 10,
};
// type 类型
const ADD = 'ADD';
const CUT = 'CUT';
// 换成函数语法
const addType = () => ({ type: ADD });
const cutType = () => ({ type: CUT });
function reducers(state = initData, action) {
switch (action.type) {
case ADD:
return {
num: state.num + 1,
};
case CUT:
return {
num: state.num - 1,
};
default:
return state;
}
}
let store = createStore(reducers);
const { num } = store.getState();
class App extends Component {
constructor(props) {
super(props);
this.state = {
num,
};
}
componentDidMount() {
this.unSubscribe = store.subscribe(() =>
this.setState({
num: store.getState().num,
}),
);
}
render() {
return (
<div>
<p>{this.state.num}</p>
{/* 通过提交函数 */}
<button onClick={() => store.dispatch(addType())}>+</button>
<button onClick={() => store.dispatch(cutType())}>-</button>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
这样一来, 使用函数的语法,也是可以的,而且这种写法,比直接提交更不容易出错,也可以统一管理type,但是,我又添加了一个减1 的操作,这样一来,就
store.dispatch()
写了两次,那如果我有很多个这种类似操作,就有点冗余了,我就想写成直接调用某个方法,比如这样的<button onClick={() => add()}>+</button>
,<button onClick={() => cut()}>-</button>
, 这样我就可以不用写dispatch
了,简化了Api语法
bindActionCreators() 方法
官方文档用法
import { createStore, bindActionCreators } from 'redux';
let add = () => ({ type: ADD });
let store = createStore();
let addFn = bindActionCreators(add, store.dispatch);
// 调用,可以看到简化了
<button onClick={() => addFn ()}> + </button>
// 或者更简单点
<button onClick={addFn}>+</button>
自己实现bindActionCreators() 方法
可以看到, bindActionCreators(action, dispatch) 接收了两个参数,一个是要派发的 type类型动作, 另一个是把 dispatch 方法传进去了,最后采用高阶函数的形式
function bindActionCreators(actionCreator, dispatch) {
// return 一个函数供外部调用
return function () {
dispatch(actionCreator());
};
}
// 使用
let store = createStore();
let add = () => ({ type: ADD });
let addFn = bindActionCreators(add, store.dispatch);
这就完事了,用法一模一样,但是一直这样写,有点分散,假如我有多个的话,这 还是写了不少代码量,也很麻烦,所以官方还提供了一个传入对象的写法
import { createStore, bindActionCreators } from 'redux';
const actions = {
add: () => ({ type: ADD }),
cut: () => ({ type: CUT }),
};
let boundAction = bindActionCreators(actions, store.dispatch);
// 调用
<button onClick={boundAction.addFn}>+</button>
实现这种传入对象的语法
也就是判断一下,传入的是个对象,还是个数组
function bindActionCreators(actionCreator, dispatch) {
if (ationCreator === 'function') {
return function () {
dispatch(actionCreator());
};
}
let boundActions = {};
for (let key in actionCreator) {
boundActions[key] = function () {
dispatch(actionCreator[key]());
};
}
return boundActions;
}
或者箭头函数,这样简化写
function bindActionCreators(actionCreator, dispatch) {
// 给每个action绑定创建函数
const bindActionCreator = (actionCreator) => () => dispatch(actionCreator());
if (typeof actionCreator === 'function') {
return bindActionCreator(actionCreator);
}
let boundActions = {};
for (let key in actionCreator) {
boundActions[key] = bindActionCreator(actionCreator[key], dispatch);
}
return boundActions;
}
处理派发action传参
派发动作时, 偶尔可能还需要传自己的参数,所以bindActionCreators函数
需要处理传参,在后边的高阶函数中
function bindActionCreators(actionCreator, dispatch) {
// 给每个action绑定创建函数
const bindActionCreator = (actionCreator) => (...args) => dispatch(actionCreator(...args));
// .....略
}