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));
// .....略
}