所以说你有这个组件结构的聊天应用程序:
<ChatApp>
<CurrentUserInfo>...</CurrentUserInfo>
<ChatsPanel>...</ChatsPanel>
<SelectedChatPanel>
<MessagesList>
<MessageBaloon>
<MessageText></MessageText>
<MessageUserHead></MessageUserHead>
</MessageBaloon>
...
</MessagesList>
<SelectedChatPanel>
</ChatApp>
Redux状态如下:
{
currentUser: ...,
chatsList: ...,
selectedChatIndex: ...,
messagesList: [ ... ]
}
如何将当前用户信息提供给<MessageUserHead>
组件(将呈现每条消息的当前用户缩略图),而不必通过所有中间组件从根组件一直传递它?
同样地,如何在不借助于暴露整个状态对象的情况下,如何为组件树中的每个表示/哑组件提供当前语言,主题等信息?
答案 0 :(得分:12)
(更新:花了一些时间在选项4上,我个人认为它是要走的路。我发布了一个基于这种方法的react-redux-controller库。)
我知道有几种方法可以从根组件,到叶组件,中间的分支中获取数据。
道具链
Redux文档,在使用react-redux的情况下,suggest通过props
将数据传递到整个分支链。我并不赞成这个想法,因为它将所有中间分支组件与今天的应用程序结构相结合。从好的方面来说,你的React代码会相当纯粹,只能在顶层与Redux本身相连。
所有组件中的选择器
或者,您可以使用connect
从Redux商店中获取数据,无论您在组件树中的位置如何。这会将您的组件彼此分离,但它会将所有耦合到Redux。我会注意到Redux的主要作者是not necessarily opposed这种方法。并且它可能更具性能,因为它可以防止由于props
实际关心的children
的变化而重新呈现中间组件。
反应children
我没有想过以这种方式做事很多,但你可以将最高级别的整个应用程序结构描述为嵌套组件,将道具直接传递给远程后代,并使用connect
在分支级别渲染注入的组件。但是,极端情况下,这会使您的容器组件变得非常复杂,尤其是对于具有多个类型子级的中间组件。由于这个原因,不确定这是否真的可行。
反应背景
正如@mattclemens首次提到的,您可以使用实验context api来分离您的中间组件。是的,实验&#34;。是的,React团队似乎并不喜欢它。但请记住,这正是Redux的dispatch
用来注入connect
和来自选择器的道具。
我认为它取得了很好的平衡。组件保持分离,因为分支组件不需要关心后代&#39;依赖。如果您只在根位置使用context
来设置上下文,那么所有后代只需要耦合到React的上下文API,而不是Redux。只要某些祖先设置了所需的context
属性,就可以自由地重新排列组件。如果设置context
的唯一组件是根组件,那么这很简单。
React团队使用$('textarea[name="latlong"]').bind('focusout',function(){
$(".polygon .geoerror").text("");
var polygon = $(this).val();
//remove extra space if its there
polygon = polygon.replace(/\s*/g, "");
var nums = polygon.split(',');
var len = nums.length;
var is_even = ( len % 2 == 0 );
if (!is_even) {
$(".polygon .geoerror").text("Mismatch of lat and long values." + polygon);
$(".polygon .geoerror").css("color", "red");
return false;
}
var validNums = true;
for(var i = 0; i < len; i++) {
if(isNaN(nums[i])) {
validNums = false;
break;
}
}
if (validNums) {
$(".polygon .geoerror").text("Polygon string is valid." + polygon);
$(".polygon .geoerror").css("color", "green");
} else {
$(".polygon .geoerror").text("Not valid." + polygon);
$(".polygon .geoerror").css("color", "red");
}
return false;
});
与全局变量进行比较,但这感觉有些夸张。这似乎更像是对我的依赖注入。
答案 1 :(得分:4)
对于所有“哑”组件的全局信息,您可以使用react contexts。
一个人为的例子
// 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库中使用了这个context approach。
更抽象地用于反应之外,你可以在状态树上使用某种类型的pluck或selector function,并且只返回哑组件所需的全局状态的子集。