【问题标题】:How to communicate UI state changes between React components with Redux?如何使用 Redux 在 React 组件之间传达 UI 状态更改?
【发布时间】:2015-11-06 15:28:05
【问题描述】:

据我了解 Redux 是将 UI 的所有状态保存在一个存储中(以便能够轻松地重现某些状态并且没有副作用)。您可以通过触发减少器的触发操作来操纵状态。

我目前正在编写一个类似博客的小型应用程序,您可以在其中简单地创建和编辑帖子。我有一个用于创建帖子的对话框,大致上App 组件的render 方法返回如下内容:

<div>
    <AppBar ... />
    <PostFormDialog
      addPost={actions.addPost}
      ref="postFormDialog" />
    <PostList
      posts={posts}
      actions={actions} />
</div>

我的问题是:对话框的状态(打开或关闭)应该是 App 组件状态对象的一部分吗?因此,是否应该通过操作触发打开和关闭对话框,而不是执行以下操作:

onTriggerCreatePostDialog(e) {
    this.refs.postFormDialog.show();
}

onTriggerCreatePostDialog 是通过“创建”按钮上的某个点击侦听器触发的。

我觉得通过一个动作来做这件事有点奇怪,因为它引入了一种“间接”。

但是,假设我想将对话框重用于编辑操作,我必须能够从组件结构中较深的元素打开对话框,例如从作为子组件的 Post 组件打开对话框。 PostList 组件。我可以做的是通过props 属性将onTriggerCreatePostDialog 函数向下传递,但这对我来说似乎很麻烦......

所以最终也是关于不处于直接父子关系的组件之间的通信。还有其他选择吗?我应该以某种方式使用全局事件总线吗?我目前很不确定。

【问题讨论】:

    标签: javascript reactjs redux


    【解决方案1】:

    在我看来,您走在正确的道路上。文档一开始可能有点棘手,但我可以告诉你我和我的团队是如何使用实现的。

    解决您的第一个问题;如果状态特定于某个组件,那么我们将该状态保留在该组件中。这方面的一个例子是一个在本地分页记录的面板——没有其他东西需要注意这种行为。所以在这种情况下,我们不会在页面更改时触发 redux 操作,这将在组件结构内部使用 refs 进行处理。

    我们的 redux 状态主要由通过 xhr 请求或从共享状态收集的数据组成。共享状态的一个示例是管理使用该范围来显示数据的多个组件之间的时间范围。在这种情况下,我们会触发一个 redux 动作;使用更改为的任何内容更新日期状态(同时还通过 xhr 更新一些其他状态项),然后最终返回到组件并重新渲染。

    话虽如此,通过 refs 触发操作是完全可以接受的,这与具体用例有关。

    解决您的第二个问题; redux 推荐使用Smart & Dumb 组件概念。所以你是对的,你可以向下传递一个函数让愚蠢的组件使用。

    我们在 connect 设置中使用 mapDispatchToProps。所以基本上你传递了一个返回函数“调度程序”对象的函数。您将能够直接在智能组件的this.props 中访问这些功能。

    mapDispatchToProps 示例

    function mapDispatchToProps(dispatch) {
      return {
        myAction: () => dispatch(actions.myAction()),
      };
    }
    

    所以这在 99% 的时间都有效,但我遇到了一些我们确实使用全局事件总线的极端情况,所以不要害怕在尝试坚持 Smart / Dumb 组件方法时同时使用这两种方法尽可能的。

    作为旁注,我建议使用 reselect 将您的 redux 状态映射到智能组件。您还可以找到其他很棒的 redux 资源 here(列出了我们使用的几个东西)。

    【讨论】:

    • 为兄弟组件触发 Redux 操作怎么样?假设您希望兄弟 A 中的一个 Redux 操作更新要确认的存储并触发要在兄弟 B 的连接中访问的道具。您是否只需在以兄弟 A 和 B 作为子级的父组件中进行连接?谢谢!
    【解决方案2】:

    对话框的状态应该在 redux 存储中,由操作触发。是否应该渲染应该通过检查 redux 存储中的状态来确定。

    App.render() 应该是这样的:

    render() {
      const { showDialog } = this.props;
    
      return (
        <div>
          <AppBar ... />
          { showDialog ? <PostFormDialog ... /> : false }
          <PostList ... />
        </div>
      );
    }
    

    mapStateToProps 类似于 state =&gt; {{ showDialog: state.showDialog }}

    就交付动作创建者而言,将其向下传递到 props 树可能是正确的方法,除非您有一个合适的位置,让另一个智能组件有意义。

    【讨论】:

    • 假设对话框不是模态的。最初它没有显示,它的状态按照您的建议进行管理。我单击一个按钮,showDialog 变为真,并显示此对话框。现在,如果我单击对话框以外的其他位置,它会再次关闭,但不会对showDialog 进行相应操作,除非我在PostFormDialog 中明确处理这种情况。在我看来,这只是对话框状态处理变得繁琐的一个例子。你会那样做吗?
    • 关于智能组件:例如,引入另一个智能组件来管理模态对话框的状态是否合理?假设该对话框可用于创建新帖子和编辑现有帖子。此外,您必须在成功创建/编辑后处理诸如“清除”对话框之类的事情......
    • 这种方法可行,但它也会破坏任何对话框出现/消失动画,不是吗?由于父组件被重新渲染,对话框将立即从屏幕上删除。我想知道最好的解决方法是什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-09
    • 2019-12-10
    • 2018-05-21
    • 2016-08-31
    • 2019-12-29
    • 2018-08-02
    • 1970-01-01
    相关资源
    最近更新 更多