什么时候bindActionCreators会在react/redux中使用?

d.c*_*ode 81 reactjs redux react-redux

bindActionCreators的Redux文档声明:

唯一的用例bindActionCreators是当你想将一些动作创建者传递给一个不知道Redux的组件时,你不想将调度或Redux存储传递给它.

什么bindActionCreators是使用/需要的例子?

哪种组件不会意识到Redux

两种选择的优点/缺点是什么?

//actionCreator
import * as actionCreators from './actionCreators'

function mapStateToProps(state) {
  return {
    posts: state.posts,
    comments: state.comments
  }
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(actionCreators, dispatch)
}
Run Code Online (Sandbox Code Playgroud)

VS

function mapStateToProps(state) {
  return {
    posts: state.posts,
    comments: state.comments
  }
}

function mapDispatchToProps(dispatch) {
  return {
    someCallback: (postId, index) => {
      dispatch({
        type: 'REMOVE_COMMENT',
        postId,
        index
      })
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

mar*_*son 47

99%的时间,它与React-Redux connect()功能一起使用,作为mapDispatchToProps参数的一部分.它可以在mapDispatch您提供的函数内显式使用,或者如果您使用对象简写语法并将一个充满动作创建者的对象传递给它,则会自动使用它connect.

我们的想法是,通过预先绑定动作创建者,您传递给的组件在connect()技术上"不知道"它已连接 - 它只知道它需要运行this.props.someCallback().另一方面,如果你没有绑定动作创建者并且被调用this.props.dispatch(someActionCreator()),那么现在组件"知道"它已连接,因为它期望props.dispatch存在.

我在我的博客文章Idiomatic Redux中写了一些关于这个主题的想法:为什么要使用动作创作者?.


Dia*_*ova 43

我不认为最受欢迎的答案,实际上是解决了这个问题.

以下所有示例基本上都做同样的事情,并遵循没有"预绑定"的概念.

// option 1
const mapDispatchToProps = (dispatch) => ({
  action: () => dispatch(action())
})


// option 2
const mapDispatchToProps = (dispatch) => ({
  action: bindActionCreators(action, dispatch)
})


// option 3
const mapDispatchToProps = {
  action: action
}
Run Code Online (Sandbox Code Playgroud)

选项#3只是选项的简写#1,所以真正的问题是为什么一个人会使用选项#1vs选项#2.我已经看到它们都在react-redux代码库中使用,我发现它相当令人困惑.

我认为混淆来自于doc 中所有示例react-redux使用的事实,bindActionCreatorsbindActionCreators的文档 (在问题本身中引用)表示不使用react-redux.

我想答案是代码库中的一致性,但我个人更喜欢在需要时明确地将调度包装在调度中.

  • 选项`#3`如何成为选项`#1'的简写? (2认同)

Cha*_* 木匠 15

更完整的示例,传递一个充满动作创建者的对象来连接:

import * as ProductActions from './ProductActions';

// component part
export function Product({ name, description }) {
    return <div>
        <button onClick={this.props.addProduct}>Add a product</button>
    </div>
}

// container part
function mapStateToProps(state) {
    return {...state};
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators({
        ...ProductActions,
    }, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(Product);
Run Code Online (Sandbox Code Playgroud)


kne*_*ola 14

我会尝试回答原来的问题......

智能和愚蠢的组件

在你的第一个问题中,你基本上首先要问为什么bindActionCreators需要,以及什么样的组件不应该知道Redux.

简而言之,这里的想法是组件应该分为智能(容器)和(表示)组件. 愚蠢的组件在需要知道的基础上工作.他们的灵魂工作是将给定的数据呈现给HTML,仅此而已.他们不应该意识到应用程序的内部工作原理.它们可以被视为应用程序的皮肤深层.

另一方面,智能组件是一种粘合剂,它为组件准备数据,并且最好不进行HTML渲染.

这种架构促进了UI层与下面的数据层之间的松散耦合.这反过来允许用其他东西(即UI的新设计)容易地替换任何两个层,这不会破坏另一层.

回答你的问题:哑组件不应该知道Redux(或者数据层的任何不必要的实现细节),因为我们可能希望将来用其他东西替换它.

您可以在Redux手册中找到更多关于此概念的信息,并在Dan Abramov的文章演示和容器组件中进行更深入的介绍.

哪个例子更好

第二个问题是关于给定示例的优点/缺点.

在第一个示例中,动作创建者在单独的actionCreators文件/模块中定义,这意味着它们可以在其他地方重用.它几乎是定义动作的标准方式.我真的没有看到任何不利之处.

第二个例子中定义了动作的创作者的内联,这具有多个缺点:

  • 动作创作者不能重复使用(显然)
  • 事物更冗长,转化为可读性更低
  • 动作类型是硬编码的 - 最好将它们consts分开定义,以便它们可以在reducers中引用 - 这样可以减少键入错误的机会
  • 定义动作创建者内联是违反推荐/预期的使用方式 - 这将使您的代码对社区的可读性降低,以防您计划共享代码

第二个例子比第一个例子有一个优势 - 编写速度更快!因此,如果您没有更好的代码计划,那可能就好了.

我希望我能够澄清一些事情......