v16.6.0 或更高版本的上下文 API 在提供上下文的组件中使用子组件时不起作用
Posted
技术标签:
【中文标题】v16.6.0 或更高版本的上下文 API 在提供上下文的组件中使用子组件时不起作用【英文标题】:v16.6.0 or higher Context API not working when child is used in component that provides the context 【发布时间】:2019-05-30 21:07:05 【问题描述】:我正在使用新的 react 上下文 API(v16.6.0 或更高版本),方法是在使用上下文的组件内声明 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
都有效
新的 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
Running Code
问题
当Provider
组件直接使用在其render()
函数中使用上下文的子组件时,为什么上下文API (>=v16.6) 不起作用(使用static contextType
)?这是错误还是已知限制?我错过了什么?
附加信息
使用<SomeContext.Consumer>
将按预期工作。
export default class ChildOne extends Component
public render()
return (
<SomeContext.Consumer>
context =>
<div>
`Context of ChildOne: $context.someValue`
</div>
</SomeContext.Consumer>
);
当然,这不是解决此问题的方法,但可能是有用的信息。
【问题讨论】:
我会说这是一个错误。考虑举报。 @estus 如果没有人在接下来的几个小时/几天内提供解决方案,我会的 【参考方案1】:我创建了一个 issue on reacts github 以发现这不是反应错误,而是 javascript/Typescript 问题。
总结
错误的导入顺序导致了“错误”。因为ChildOne
是在上下文声明之前导入的(在ParentWithContext
中),所以SomeContext
在ChildOne
中导入的时候实际上是undefined
。
import ChildOne from "./ChildOne";
export const SomeContext = React.createContext(
someValue: false
);
所以一种解决方案是交换这两个声明
export const SomeContext = React.createContext(
someValue: false
);
import ChildOne from "./ChildOne";
或者简单地(和恕我直言)将上下文提取到它自己的文件中。 这样您就可以排除以后出现的任何类似问题。
【讨论】:
以上是关于v16.6.0 或更高版本的上下文 API 在提供上下文的组件中使用子组件时不起作用的主要内容,如果未能解决你的问题,请参考以下文章
如何在android 10或更高版本中获得“总是”位置的许可? (高于 API 29)?
MVC 脚手架不支持 Entity Framework 6 或更高版本
库版本不兼容:nokogiri.bundle 需要 8.0.0 或更高版本,但 libiconv.2.dylib 提供 7.0.0 版本
更新到 Go 1.15 或更高版本后出现错误“panic: cannot create context from nil parent”