通过道具将动作传递到堆栈

Passing actions down the stack via props

我已经使用 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 组件没有对其父组件的引用,所以我不知道应该从哪里注入这个道具(在这个例子中很明显,但我希望你能明白) .

如果我有更深层次的组件结构呢?

这个方法正确吗?

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

更新:

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

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

如果你使用 redux,你应该了解 dumb 和 smart 组件。所以我们使用这个结构:

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 函数将在 dumb 组件的 props 中。在那里你可以使用 this.props.onCreate 并调用它或进一步传递它。

传递动作 - 像任何其他道具一样 - 从 parent 到 child 再到 grandchild 等是惯用的 React 方式。我认为你的做法是正确的;即使感觉不对。

但是还有几个选择。

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

此外,还有一种特定于 Redux 的方法,您可以使您选择的任何低阶节点成为 "smart component"(在 Redux 意义上)。也就是说,您将 class 导出包装在连接函数中,以将其直接插入商店,其方式与您对 Root 节点所做的完全相同。

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

在 Redux github 回购的问题部分有一个讨论关于是否可以使用多个连接或者是否应该通过 props 从顶部向下传递所有内容,并且在那里 Dan Abramov( Redux 的创建者说:

[...]

Nobody advocates a single connect.

[...]

The "single" only refers to small apps like the one we create in the example. Please feel free to amend the docs to better clarify this. I am now busy with other projects so please don't expect this issue to get any movement unless somebody makes a PR. You can do it too.

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