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 组件(右下方)。

ChildOneChildTwo

这两个组件只是简单地使用上面的上下文并显示它。

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 中删除 &lt;ChildOne/&gt; 时,它突然对 ChildOneChildTwo 都有效

新的 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)?这是错误还是已知限制?我错过了什么?

附加信息

使用&lt;SomeContext.Consumer&gt; 将按预期工作。

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中),所以SomeContextChildOne中导入的时候实际上是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 版本

如何在同一版本中使用更低和更高的 API 调用? [复制]

语义版本控制问题和 npm 5 或更高版本

更新到 Go 1.15 或更高版本后出现错误“panic: cannot create context from nil parent”