Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2018-08-26]: 阅读Redux源码03 - bindActionCreators #7

Open
Lemonreds opened this issue Aug 26, 2018 · 0 comments
Open

[2018-08-26]: 阅读Redux源码03 - bindActionCreators #7

Lemonreds opened this issue Aug 26, 2018 · 0 comments

Comments

@Lemonreds
Copy link
Owner

回顾 actionCreator

接下来说说 bindActionCreators 这个方法,bindActionCreators 不难理解,但在此之前需要回顾一下我们之前讲到的 actionCreator 的概念,我们知道,要更新state树的唯一途径是发起一个action,如:

dispatch({
    type: 'ADD_TODO',
    text: 'ADD TODO AGAIN.' 
})

每个action都需要写type,这样每次写起来就会觉得冗余,于是产生了 actionCreator 的概念,我们写一个函数,帮我们写好指定的type,传入不同的信息载荷就可以了,如:

function addTodo(text){
    return{
         type: 'ADD_TODO',
         text
    }
}

上面就是一个actionCreator 的例子,注意actionCreator 和action是两个不同的概念,action是对象,用来描述state发生了什么变化,而actionCreator 是函数,是用来生成action的工厂。

bindActionCreator 函数

再然后来看看bindActionCreators 方法用到的一个函数:

function bindActionCreator(actionCreator, dispatch) {
  return function() {
    return dispatch(actionCreator.apply(this, arguments))
  }
}

函数的两个参数:

  • actionCreator 函数,用于生产action的工厂
  • dispatch 函数,也就是Store.dispatch ()

函数非常简单,也就是将 dispatch 和 actionCreator 绑定返回一个新的函数,使用这个函数时会直接 dispatch 一个 action,变得更加简便,如:

let actionCreator = (text)=>({
     type: 'ADD_TODO,
     text
})

let addTodo = bindActionCreator(actionCreator , Store.dispatch)
// 调用
addTodo('ADD SOMETHING’) 
// 等价于:
dispatch({
    type: 'ADD_TODO',
    text: 'ADD SOMETHING'
})

也就是说 actionCreator 帮我们省略了重复书写action.type , bindActionCreator 帮我们省略了重复书写 dispatch,而且还可以隐藏 dispatch 参数。再来看看bindActionCreators方法就不难理解了:

bindActionCreators 方法

export default function bindActionCreators(actionCreators, dispatch) {

  // 如果传入的actionCreators是一个函数,则直接绑定返回一个新的函数
  if (typeof actionCreators === 'function') {
    return bindActionCreator(actionCreators, dispatch)
  }
  // 如果传入的actionCreators是Object类型 
  // Object的字段都是一个个 actionCreator
  if (typeof actionCreators !== 'object' || actionCreators === null) {
    throw new Error(
      `xxxx`
    )
  }
  
  const keys = Object.keys(actionCreators) // 所有的key
  const boundActionCreators = {} // 最终返回的对象

  for (let i = 0; i < keys.length; i++) {
    const key = keys[i]
    const actionCreator = actionCreators[key]
    // 过滤不合法的值 逐一进行绑定
    if (typeof actionCreator === 'function') {
      boundActionCreators[key] = bindActionCreator(actionCreator, dispatch)
    }
  }
  //返回最终绑定好 actionCreator 对象
  return boundActionCreators
}

最后

总结一下 bindActionCreators 方法,首先参数dispatch是必须的,也就是Store.dispatch()。

  • 如果你传入的 actionCreators 参数仅仅是一个 actionCreator 函数,那么直接绑定 actionCreator 和 dispatch,返回一个新函数,调用函数传入action的载荷,就可以直接发起一个指定type的action。
  • 如果你传入的 actionCreators 参数是一个对象,那么对象的字段必须是一个个actionCreator函数,返回一个对象,对象逐一进行绑定,每个字段都是绑定好的函数,调用它们传入action的载荷,就会直接发起一个指定type的action。

使用场景

Redux文档上关于何时使用到此API是这样说的:
惟一会使用到 bindActionCreator 的场景是当你需要把 action creator 往下传到一个组件上,却不想让这个组件觉察到 Redux 的存在,而且不希望把 dispatch 或 Redux store 传给它。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant