v16.6.0 或更高版本上下文 API 在提供上下文的组件中使用子项时不起作用
v16.6.0 or higher Context API not working when child is used in component that provides the context
我正在使用 React(v16.6.0 或更高版本)的新上下文 API,方法是在使用上下文的组件内声明 public static contextType
。
只要声明 Provider
的组件不直接使用在其 render()
方法中使用上下文的组件,这就可以正常工作。
示例:
ParentWithContext
这是创建和提供上下文的组件。
export const SomeContext = React.createContext({
someValue: false
});
export default class ParentWithContext extends Component {
public render(){
const contextValue = {someValue: true};
return (
<SomeContext.Provider value={contextValue}>
<ChildOne />
{this.props.children}
</SomeContext.Provider>
);
}
}
请注意,此组件在其 render()
方法中使用了 ChildOne
组件(见右下方)。
ChildOne 和 ChildTwo
这两个组件简单地使用上面的上下文并显示它。
export default class ChildOne extends Component {
public static contextType = SomeContext;
public render(){
return (
<div>
{`Context of ChildOne: ${this.context.someValue}`}
</div>
);
}
}
export default class ChildTwo extends Component {
public static contextType = SomeContext;
public render(){
return (
<div>
{`Context of ChildTwo: ${this.context.someValue}`}
</div>
);
}
}
index.tsx
class App extends Component {
render() {
return (
<ParentWithContext>
<ChildTwo />
<ChildOne />
</ParentWithContext>
);
}
}
运行 此示例将生成以下行:
Context of ChildOne: undefined
Context of ChildTwo: true
Context of ChildOne: undefined
所以 ChildTwo
似乎从 this.context
收到了正确的信息,而 ChildOne
什么也没收到。
现在出现了奇怪的部分(对我来说):当您从 ParentWithContext
中删除 <ChildOne/>
时,它突然对 ChildOne
和 ChildTwo
[=35= 都有效]
新建 ParentWithContext
export default class ParentWithContext extends Component {
public render(){
const contextValue = {someValue: true};
return (
<SomeContext.Provider value={contextValue}>
{this.props.children}
</SomeContext.Provider>
);
}
}
新建HTML输出
Context of ChildTwo: true
Context of ChildOne: true
问题
为什么 API (>=v16.6) 当 Provider
组件直接使用子组件时,上下文 API (>=v16.6) 不起作用(使用 static contextType
) render()
函数?这是错误还是已知限制?我错过了什么?
补充信息
使用 <SomeContext.Consumer>
将按预期工作。
export default class ChildOne extends Component {
public render(){
return (
<SomeContext.Consumer>
{context =>
<div>
{`Context of ChildOne: ${context.someValue}`}
</div>
}
</SomeContext.Consumer>
);
}
}
当然这不是这个问题的解决方案,但可能是有用的信息。
我正在创建一个 issue on reacts github 以发现它不是反应错误而是 Javascript/Typescript 问题。
总结
错误的导入顺序导致 "bug"。因为 ChildOne
是在声明上下文之前导入的(在 ParentWithContext
中),所以 SomeContext
在 ChildOne
.[=18= 中导入时实际上是 undefined
]
import ChildOne from "./ChildOne";
export const SomeContext = React.createContext({
someValue: false
});
所以一个解决方案是交换这两个声明
export const SomeContext = React.createContext({
someValue: false
});
import ChildOne from "./ChildOne";
或者简单地(和 IMHO 清洁器)将上下文提取到它自己的文件中。
这样您以后就可以排除任何类似的问题。
我正在使用 React(v16.6.0 或更高版本)的新上下文 API,方法是在使用上下文的组件内声明 public static contextType
。
只要声明 Provider
的组件不直接使用在其 render()
方法中使用上下文的组件,这就可以正常工作。
示例:
ParentWithContext
这是创建和提供上下文的组件。
export const SomeContext = React.createContext({
someValue: false
});
export default class ParentWithContext extends Component {
public render(){
const contextValue = {someValue: true};
return (
<SomeContext.Provider value={contextValue}>
<ChildOne />
{this.props.children}
</SomeContext.Provider>
);
}
}
请注意,此组件在其 render()
方法中使用了 ChildOne
组件(见右下方)。
ChildOne 和 ChildTwo
这两个组件简单地使用上面的上下文并显示它。
export default class ChildOne extends Component {
public static contextType = SomeContext;
public render(){
return (
<div>
{`Context of ChildOne: ${this.context.someValue}`}
</div>
);
}
}
export default class ChildTwo extends Component {
public static contextType = SomeContext;
public render(){
return (
<div>
{`Context of ChildTwo: ${this.context.someValue}`}
</div>
);
}
}
index.tsx
class App extends Component {
render() {
return (
<ParentWithContext>
<ChildTwo />
<ChildOne />
</ParentWithContext>
);
}
}
运行 此示例将生成以下行:
Context of ChildOne: undefined
Context of ChildTwo: true
Context of ChildOne: undefined
所以 ChildTwo
似乎从 this.context
收到了正确的信息,而 ChildOne
什么也没收到。
现在出现了奇怪的部分(对我来说):当您从 ParentWithContext
中删除 <ChildOne/>
时,它突然对 ChildOne
和 ChildTwo
[=35= 都有效]
新建 ParentWithContext
export default class ParentWithContext extends Component {
public render(){
const contextValue = {someValue: true};
return (
<SomeContext.Provider value={contextValue}>
{this.props.children}
</SomeContext.Provider>
);
}
}
新建HTML输出
Context of ChildTwo: true
Context of ChildOne: true
问题
为什么 API (>=v16.6) 当 Provider
组件直接使用子组件时,上下文 API (>=v16.6) 不起作用(使用 static contextType
) render()
函数?这是错误还是已知限制?我错过了什么?
补充信息
使用 <SomeContext.Consumer>
将按预期工作。
export default class ChildOne extends Component {
public render(){
return (
<SomeContext.Consumer>
{context =>
<div>
{`Context of ChildOne: ${context.someValue}`}
</div>
}
</SomeContext.Consumer>
);
}
}
当然这不是这个问题的解决方案,但可能是有用的信息。
我正在创建一个 issue on reacts github 以发现它不是反应错误而是 Javascript/Typescript 问题。
总结
错误的导入顺序导致 "bug"。因为 ChildOne
是在声明上下文之前导入的(在 ParentWithContext
中),所以 SomeContext
在 ChildOne
.[=18= 中导入时实际上是 undefined
]
import ChildOne from "./ChildOne";
export const SomeContext = React.createContext({
someValue: false
});
所以一个解决方案是交换这两个声明
export const SomeContext = React.createContext({
someValue: false
});
import ChildOne from "./ChildOne";
或者简单地(和 IMHO 清洁器)将上下文提取到它自己的文件中。 这样您以后就可以排除任何类似的问题。