如何将全局状态数据处理到Redux中的深度嵌套组件中

How to handle global state data into deeply nested components in Redux?

本文关键字:深度 嵌套 组件 Redux 全局 状态 数据处理      更新时间:2023-09-26

假设您有一个具有以下组件结构的聊天应用程序:

<ChatApp>
  <CurrentUserInfo>...</CurrentUserInfo>
  <ChatsPanel>...</ChatsPanel>
  <SelectedChatPanel>
    <MessagesList>
      <MessageBaloon>
        <MessageText></MessageText>
        <MessageUserHead></MessageUserHead>
      </MessageBaloon>
      ...
    </MessagesList>
  <SelectedChatPanel>
</ChatApp>

和一个类似于Redux的状态:

{ 
  currentUser: ...,
  chatsList: ...,
  selectedChatIndex: ...,
  messagesList: [ ... ]
}

如何使当前用户信息可用于<MessageUserHead>组件(将为每条消息呈现当前用户缩略图),而不必从根组件一直传递到所有中间组件?

同样,在不暴露整个状态对象的情况下,如何使当前语言、主题等信息可用于组件树中的每个表示/哑组件?

(更新:在选项4上花了一些时间后,我个人认为这是可行的。我发布了一个库,围绕这种方法构建的react redux控制器。)

我知道有几种方法,从根组件到叶组件,通过在中间的分支获取数据。

道具链

在使用react Redux的情况下,Redux文档建议通过props将数据传递到整个分支链。我不赞成这个想法,因为它将所有中间分支组件与当今的应用程序结构相耦合。从好的方面来看,React代码将相当纯粹,并且只与顶级的Redux本身相耦合。

所有组件中的选择器

或者,您可以使用connect使Redux存储中的数据可用,无论您在组件树中的位置如何。这将使组件彼此解耦,但它将所有都耦合到Redux。我要指出的是,Redux的主要作者并不一定反对这种做法。它可能更具性能,因为它防止了由于props中的更改而导致的中间组件的重新呈现,而这些更改实际上并不关心。

反应children

我没有想过用这种方式做很多事情,但可以在最高级别将整个应用程序结构描述为嵌套组件,将props直接传递给远程子体,并使用children在分支级别渲染注入的组件。然而,如果走到极端,这将使容器组件变得非常复杂,尤其是对于具有多个类型的子级的中间组件。出于这个原因,我不确定这是否真的可行。

反应上下文

正如@mattclemens首先提到的,您可以使用实验上下文api来解耦中间组件。是的,这是"实验性的"。是的,React团队似乎并不喜欢它。但请记住,这正是Redux的connect用来注入dispatch和选择器道具的。

我认为它达到了很好的平衡。组件保持解耦,因为分支组件不需要关心子体的依赖关系。如果只在根上使用connect来设置上下文,那么所有子代只需要耦合到React的上下文API,而不需要耦合到Redux。只要某个祖先设置了所需的context属性,就可以自由地重新排列组件。如果设置context的唯一组件是根组件,那么这是非常正确的。

React团队将使用context与全局变量进行了比较,但这感觉有些夸张。对我来说,这更像是依赖注入。

对于所有"dumb"组件全局的信息,可以使用react上下文。

一个人为的示例

// redux aware component
var ChatApp = React.createClass({
  childContextTypes: {
    language: React.PropTypes.string
  },
  getChildContext: function() {
    // or pull from your state tree
    return {language: "en"};
  },
  ...
}
// dumb components
var ExDumb = React.createClass({
  contextTypes: {
    language: React.PropTypes.string
  },
  render: function() {
    var lang = this.context.language;
    return ( <div /> );
   }
 });

作为对评论的回应,redux在他们的react redux库中使用了这种上下文方法。

更抽象地说,对于react之外的使用,您可以在状态树上使用某种提取或选择器函数,并且只返回哑组件所需的全局状态的子集。