redux3 - 通过提交函数派发action及 手写 实现 bindActionCreators 函数

redux源码参考

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值