【问题标题】:Passing actions down the stack via props通过 props 向下传递动作
【发布时间】:2016-02-04 19:09:36
【问题描述】:

我已经使用 Redux 几个星期了,我对它非常满意,而且我已经习惯了 Redux 的方式。我将它与 React 一起使用。仍然有很多东西要学,因为这两件事对我来说都是新的。

我有一个问题 - 也许我做错了什么......让我告诉你:

我的组件结构如下所示:

App  //root of the application aka smart component
  CampaignTable 
    CampaignHeaderRow 
      CampaignHeader 
    CampaignDataRow
      CampaignData

App组件初始化为(仅相关代码):

import * as DashboardActions from '../actions.js'

function select(state){
  return {
    campaigns: state.campaigns,  // array of campaign objects, has name, id, time created etc
    order: state.order // sort format "byWhichField" 
                       // will affect the way how campaigns are displayed
  }
}

function mapDispatchToProps(dispatch){
  return bindActionCreators(DashboardActions, dispatch) 
}

export default connect(select, mapDispatchToProps)(App);

应用现在可以访问状态和所有动作作为道具。

我现在看到的问题是:

我希望 CampaignHeader 触发将更改 state.order 状态的操作。假设我会让 CampaignHeader 内的<th>Text</th> 可点击。这将触发更改 state.order 的操作,进而影响下一次重新呈现时的广告系列顺序。

所以我在 App 道具中可以使用我的操作。将其传递给 CampaignHeader 我必须:

  • 将其作为道具传递给 CampaignHeader
  • 将其分配给 CampaignHeader 内的变量,并将其作为道具传递给 CampaignHeaderRow
  • 将其分配给 CampaignHeaderRow 内的变量,并将其作为道具传递给 CampaignHeader
  • 将其分配给 CampaignHeader 中的变量并在 onClick 事件中触发操作....

这是很多样板文件、作业和包传递!只是为了触发行动。

沿途的所有组件都知道这个动作。

当我决定实现这个功能时,我打开了 CampaignHeader 组件文件。我已经添加了逻辑并调用了动作,我已经将动作添加到动作文件中。我所需要的只是获得一套道具。 CampaignHeader 组件不包含对其父级的引用,所以我不知道应该从哪里注入这个道具(在这个例子中很明显,但我希望你明白)。

如果我有更深的组件结构会怎样?

这种方法正确吗?

我可以用不同的方式解决这个问题吗?

更新:

正如@Errorpro 建议的那样,将 single actionstate.order 连接到 CampaignHeader 是否可以?

担心:如果我会做一次,我会一直做。

【问题讨论】:

    标签: reactjs redux


    【解决方案1】:

    在 Redux github repo 的 issue-section 中讨论了是否可以使用多个连接,或者是否所有内容都应该通过 props 从顶部向下传递,并且在那里 Dan Abramov(Redux 的创建者说:

    [...]

    没有人提倡单一连接。

    [...]

    “单一”仅指像我们在 例子。请随时修改文档以更好地澄清这一点。一世 我现在正忙于其他项目,所以请不要指望这个问题 除非有人提出公关,否则会有任何动静。你也可以。

    该评论在上下文中可能更有意义,因此请查看整个问题线程https://github.com/rackt/redux/issues/419#issuecomment-140782462

    【讨论】:

      【解决方案2】:

      如果您使用 redux,您应该了解哑组件和智能组件。所以我们使用这个结构:

      component
        index.js
        Component.js
        ComponentContainer.js
      

      哑组件只是获取道具并渲染它。智能组件更有趣。这里是:

      export default compose(
        relay({
          fragments: {
            viewer: () => Relay.QL`
              fragment on Viewer {
                 any data from relay
              }
            `,
          },
        }),
        connect(
          null,
          {
            onCreate: createUserAction,
          },
          (stateProps, actionProps, parentProps) => ({
            ...parentProps,
            onCreate={() => actionProps.onCreate('user')},
          })
        ),
      )(Component); 
      

      所以,parentProps 和 onCreate 函数将在哑组件的 props 中。在那里,您可以使用 this.props.onCreate 并调用它或将其传递得更远。

      【讨论】:

      • 但是传递更远是我的问题,在我的简单示例中我必须这样做 4 次。我知道流程是如何工作的,只是觉得这样做很奇怪
      • 在 react.js 中只有一种正确的方法可以进一步传递它 - 道具。如果你使用 redux-connect 你的方式是好的。如果您需要在最终区分中执行此操作,您可以在那里使用智能组件并在那里调用您的操作。在您的情况下,最好创建 CampaignHeaderContainer 并在那里连接调度和操作。就像我的例子一样。
      • 所以您建议添加另一个连接到 CampaignHeaderRow
      • 是的,为什么不呢?您可以将任何组件连接到 redux。没关系。
      • 不不,您想在 CampaignHeader 中触发操作,对吗?
      【解决方案3】:

      传递动作 - 就像任何其他道具一样 - 从父母到孩子再到孙子等等是惯用的 React 方式。我认为您的方法是正确的;即使感觉不对。

      但是有几个选择。

      React 中有一个特性叫做上下文。上下文允许将字段从高阶组件传递到低阶组件,同时跳过中间人。但是,这是一个实验性功能,所以我建议现在避免使用它。 https://facebook.github.io/react/docs/context.html

      此外,还有一种 Redux 特定的方式,您可以在其中创建您选择的“智能组件”(在 Redux 意义上)的任何低阶节点。也就是说,您将您的类导出包装在 connect 函数中以将其直接插入到存储中,这与您对 Root 节点所做的方式完全相同。

      我个人倾向于坚持自上而下的方式。可能涉及相当多的样板,但至少这意味着您的应用程序很容易推理。

      【讨论】:

      • 所以您不会想将商店的单个操作和一小部分非常具体的部分连接到CampaignHeader 正如@Errorpro 建议的那样?
      • 我的方法通常是最小化我的智能组件。即单个智能根组件。或者,当使用 react-router 时,几个智能路由处理程序。但是做任何你认为有意义的事情。
      • 这是一个 javascript,所以它是一个狂野的西部......你可以做任何你喜欢的事情;P 我可以让我的商店全球化并向世界展示中间。我更感兴趣的是获得关于社区如何解决这个问题的一般意见。谢谢你的伙伴!:)
      猜你喜欢
      • 2019-07-26
      • 2016-10-05
      • 2019-06-08
      • 1970-01-01
      • 1970-01-01
      • 2021-12-26
      • 2021-03-21
      • 2016-09-29
      • 2021-01-11
      相关资源
      最近更新 更多