我知道在 ReactJS 中,“上下文”可用于将数据从组件传递到其祖先。然而,这个上下文可以沿着层次结构修改吗?如果是,如何描述这种行为?
例如:假设组件嵌套如下:(A -> B -> C) 组件 B 是组件 A 的子级,组件 C 是组件 B 的子级。如果 A 通过向下传递一些数据上下文,它可以同样从 B 和 C 访问。但是,B 可以在传递给 C 之前修改此上下文吗?
最佳答案
是的。考虑以下两个示例,每个示例都涉及三个嵌套组件。这两个示例都使用以下 HTML 文件:
文件-index.html
<!DOCTYPE html>
<html>
<head>
<title>Hello React</title>
<!-- Not present in the tutorial. Just for basic styling. -->
<link rel="stylesheet" href="css/base.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.0/JSXTransformer.js"></script>
</head>
<body>
<div id="content"></div>
<script type="text/jsx" src="components/ParentComponent.jsx"></script>
<script type="text/jsx" src="components/ChildComponent.jsx"></script>
<script type="text/jsx" src="components/GrandchildComponent.jsx"></script>
<script type="text/jsx">
React.render(<ParentComponent />, document.getElementById('content'));
</script>
</body>
</html>
示例 1:
文件 - ParentComponent.jsx
var ParentComponent = React.createClass({
render: function () {
console.log("context in render method of ParentComponent: ");
for(var propName in this.context)
{
console.log(propName + ": " + this.context[propName]);
}
return (
<div>
<h1>Text displayed by ParentComponent</h1>
<ChildComponent />
</div>
);
},
//for sending to descendants
childContextTypes: {
styleA: React.PropTypes.object,
},
getChildContext() {
return {
styleA: customStyleA
};
}
});
var customStyleA = {
color: 'blue'
};
文件 - ChildComponent.jsx
var ChildComponent = React.createClass({
contextTypes: {
styleA: React.PropTypes.object
},
render: function () {
console.log("context in render method of ChildComponent: ");
for(var propName in this.context)
{
console.log(propName + ": " + this.context[propName]);
}
return (
<div>
<h1 style={this.context.styleA}>Text displayed by ChildComponent</h1>
<GrandchildComponent />
</div>
);
},
//for sending to descendants
childContextTypes: {
styleB: React.PropTypes.object,
},
getChildContext() {
return {
styleB: customStyleB
};
}
});
var customStyleB = {
color: 'red'
};
文件 - GrandchildComponent.jsx
var GrandchildComponent = React.createClass({
contextTypes: {
styleA: React.PropTypes.object,
styleB: React.PropTypes.object
},
render: function () {
console.log("context in render method of GrandchildComponent: ");
for(var propName in this.context)
{
console.log(propName + ": " + this.context[propName]);
}
return (
<h1 style={this.context.styleB}>Text displayed by GrandchildComponent</h1>
);
}
});
运行此示例后,这是控制台中的输出:
context in render method of ParentComponent:
context in render method of ChildComponent:
styleA: [object Object]
context in render method of GrandchildComponent:
styleA: [object Object]
styleB: [object Object]
可以看出,在本例中,ChildComponent
向上下文对象添加了一个新的 key:value
对。因此,ChildComponent 的 getChildContext() 函数返回的对象已添加到上下文中。
在输出中,第一行文本为黑色,第二行文本为蓝色,最后一行文本为红色。
示例 2
文件 - ParentComponent.jsx
var ParentComponent = React.createClass({
render: function () {
console.log("context in render method of ParentComponent: ");
for(var propName in this.context)
{
console.log(propName + ": " + this.context[propName]);
}
return (
<div>
<h1>Text displayed by ParentComponent</h1>
<ChildComponent />
</div>
);
},
//for sending to descendants
childContextTypes: {
styleA: React.PropTypes.object,
},
getChildContext() {
return {
styleA: customStyleA
};
}
});
var customStyleA = {
color: 'blue'
};
文件 - ChildComponent.jsx
var ChildComponent = React.createClass({
contextTypes: {
styleA: React.PropTypes.object
},
render: function () {
console.log("context in render method of ChildComponent: ");
for(var propName in this.context)
{
console.log(propName + ": " + this.context[propName]);
}
return (
<div>
<h1 style={this.context.styleA}>Text displayed by ChildComponent</h1>
<GrandchildComponent />
</div>
);
},
//for sending to descendants
childContextTypes: {
styleA: React.PropTypes.object,
},
getChildContext() {
return {
styleA: customStyleB
};
}
});
var customStyleB = {
color: 'red'
};
文件 - GrandchildComponent.jsx
var GrandchildComponent = React.createClass({
contextTypes: {
styleA: React.PropTypes.object,
styleB: React.PropTypes.object
},
render: function () {
console.log("context in render method of GrandchildComponent: ");
for(var propName in this.context)
{
console.log(propName + ": " + this.context[propName]);
}
return (
<h1 style={this.context.styleA}>Text displayed by GrandchildComponent</h1>
);
}
});
运行此示例后,这是控制台中的输出:
context in render method of ParentComponent:
context in render method of ChildComponent:
styleA: [object Object]
context in render method of GrandchildComponent:
styleA: [object Object]
styleB: undefined
可以看出,在本例中,ChildComponent
尝试向上下文添加一个新的 key:value
对。但是,由于该键已经存在,因此其现有值被 ChildComponent
提供的新值替换。本质上,新值覆盖了以前的值。
输出与第一个示例相同。所以一般来说,可以推断上下文可以被层次链上的组件修改。此外,如果此修改涉及现有键,则与该键对应的值将被覆盖(替换)。否则,新的键:值对将简单地添加到上下文对象中。
关于ReactJS 沿层次结构覆盖或编辑上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32340799/