ReactJS 沿层次结构覆盖或编辑上下文

标签 reactjs overriding components

我知道在 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/

相关文章:

javascript - 如何处理未接收 props 的 React 组件

angular - 在 Angular 5 中更新数据库后刷新组件

javascript - 在传单中使用react-leaflet-draw创建新层之前删除层

javascript - 如何防止在 React 应用程序中拖放图像?

c# - 在基类中将 ToString 标记为虚拟,会发生什么?

typescript :使用可选参数重载: "Overload signature is not compatible with function implementation."

java - Swing 和 WebEditorKit - 在 SwingFrame 中显示我的浏览器

css - 样式组件组织

javascript - 使用 useEffect 填充多个下拉数据

java - 如果方法中参数的类扩展了抽象方法中使用的参数的类,则覆盖方法中参数的类