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

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 中删除 <ChildOne/> 时,它突然对 ChildOneChildTwo[=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

Running Code

问题

为什么 API (>=v16.6) 当 Provider 组件直接使用子组件时,上下文 API (>=v16.6) 不起作用(使用 static contextTyperender()函数?这是错误还是已知限制?我错过了什么?

补充信息

使用 <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 中),所以 SomeContextChildOne.[=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 清洁器)将上下文提取到它自己的文件中。 这样您以后就可以排除任何类似的问题。