如何将全局状态数据处理到Redux中的深度嵌套组件中
How to handle global state data into deeply nested components in Redux?
假设您有一个具有以下组件结构的聊天应用程序:
<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之外的使用,您可以在状态树上使用某种提取或选择器函数,并且只返回哑组件所需的全局状态的子集。
- BatmanJS:深度嵌套路由
- JavaScript中的深度嵌套函数
- 深度嵌套的backbone.js对象会导致错误
- 编码为深度嵌套对象的 HTML 字段 json
- 使用underscore.js在深度嵌套的JSON中查找值
- 如何访问Vue.js中深度嵌套的子组件中的数据
- 如何将新项推送到不可变JS中的深度嵌套记录中
- Ramda js:用于具有嵌套对象数组的深度嵌套对象的镜头
- 如何访问深度嵌套的 JSON 对象中的项目
- 平展深度嵌套的对象数组
- 如何在不可变JS中存储和更新深度嵌套的结构
- 使用 lodash 按属性名称提取深度嵌套的子对象
- 具有深度嵌套集合的 Angular 性能和数据绑定
- 下划线.js :深度嵌套对象中的匹配字符串
- JavaScript承诺:具有绑定的深度嵌套上下文(this)
- 避免在ES6 JavaScript web项目中进行深度嵌套模块导入
- 将javascript与具有深度嵌套的c#代码混合使用.正在尝试制作外部文件
- Sails.js/Waterline填充深度嵌套关联
- 如何将全局状态数据处理到Redux中的深度嵌套组件中
- AngularJS从深度嵌套的jsonp渲染