如何使用Redux在React组件之间传递UI状态变化?

16

据我理解,Redux 是为了将 UI 状态集中存储在一个仓库中(以便轻松还原某些状态并且不产生副作用)。您可以通过触发触发器来操作状态,从而激活 reducers。

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

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

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

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

其中onTriggerCreatePostDialog是通过某个点击监听器在"创建"按钮或类似按钮上触发的。

对我来说,通过操作来完成这个功能似乎有点奇怪,因为它引入了一种"间接性"

然而,假设我想要重复使用这个对话框以进行编辑操作,我必须能够从组件结构中更深层次的元素打开对话框,例如从作为PostList组件的子组件的Post组件中。我可以通过props属性将onTriggerCreatePostDialog函数向下传递到层次结构中,但我认为这很麻烦...

所以最终也涉及到在不直接存在父子关系的组件之间进行通信。还有其他选择吗?我应该如何利用全局事件总线?我目前非常不确定。

2个回答

7

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

回答你的第一个问题; 如果状态只属于某个组件,那么我们将该状态与组件一起保存。例如,其中一个面板本地分页记录 --- 没有其他东西需要知道这种行为。因此,在这种情况下,当页面更改时,我们不会触发redux操作,而是在组件结构内部使用refs处理。

我们的redux状态主要由通过xhr请求收集的数据或共享状态组成。共享状态的一个例子是管理多个使用该范围来显示数据的组件之间的时间范围。在这种情况下,我们将触发redux操作; 使用改变后的日期状态更新日期状态(同时通过xhr更新一些其他状态项),并最终返回到组件进行重新呈现。

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

回答你的第二个问题; redux建议使用“聪明和愚蠢”的组件概念。所以你说的传递函数给愚蠢的组件去利用是对的。

我们在我们的connect设置中使用mapDispatchToProps。因此,基本上您会传递一个返回“分派器”函数对象的函数。您将能够直接访问这些函数在你聪明的组件的 this.props 中。

mapDispatchToProps的示例:

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

这通常可行99%的时间,但我遇到了一些特殊情况,需要使用全局事件总线,因此在尽可能坚持智能/哑组件方法的同时,不要害怕同时利用两者。 另外,我建议使用reselect将redux状态映射到智能组件。您还可以在这里找到其他很棒的redux资源(列出了我们使用的几个项目)。

1
触发Redux动作以供兄弟组件使用怎么样?假设你想在兄弟组件A中有一个Redux动作,它更新存储以被确认并触发兄弟组件B的connect中访问props。你只需要在父组件中拥有兄弟组件A和B作为子组件的connect吗?谢谢! - Con Antonakos

2

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

App.render() 应该像这样:

render() {
  const { showDialog } = this.props;

  return (
    <div>
      <AppBar ... />
      { showDialog ? <PostFormDialog ... /> : false }
      <PostList ... />
    </div>
  );
}

如果你有一个类似于state => {{ showDialog: state.showDialog }}mapStateToProps,那么你可以成为一个有用的助手。

在传递动作创建器方面,将其通过props树向下传递可能是正确的方法,除非你有一个合适的位置来放置另一个智能组件。


假设对话框不是模态的。初始状态它没有被显示,而且它的状态管理如你所提议的那样。我点击一个按钮,showDialog 变为真值并显示出该对话框。现在,如果我点击对话框以外的地方,则该对话框会关闭,但 showDialog 不会相应地被处理,除非我在 PostFormDialog 中显式地处理这种情况。这只是一个例子,其中对话框状态的处理变得麻烦了,在我看来。无论如何,你想以这种方式处理吗? - B zum S
关于智能组件:是否引入另一个智能组件来管理模态对话框的状态可能是合理的,例如?假设该对话框可用于创建新帖子和编辑现有帖子。此外,您还必须处理诸如成功创建/编辑后“清除”对话框等事项... - B zum S
这种方法可以工作,但它也会破坏任何对话框的出现/消失动画,不是吗?由于父组件正在重新渲染,对话框将立即从屏幕上移除。我想知道最好的解决方法是什么? - Igor Bukin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接