【问题标题】:React JS: Find out if component is inside a context providerReact JS:找出组件是否在上下文提供者中
【发布时间】:2021-11-12 02:27:15
【问题描述】:

我正在使用 React 的 Context API 将一些上下文传递给较低级别​​的组件。

我希望能够在没有上下文提供程序的情况下运行组件(用于测试)。为此,我需要检查我的组件周围是否有上下文提供程序。

示例代码:

const Wrapper = () => {

  // in my real app, there are some levels 
  // between the provider and the child component

  return <NameProvider value={name: 'User'}>
    <ChildComponent />
  </NameProvider>
}

const ChildComponent = () => {
  if (/* what can I put here ? */) {
    // inside Provider
    return <NameConsumer>
      {context => <span>{context.name}</span>}
    </NameConsumer>
  } else {
    // no provider available, e.g. in a test file
    return <span>Test Text</span>
  }
}

这个问题不是专门针对测试的。在其他情况下,组件可能需要在上下文提供程序内部和外部工作。

【问题讨论】:

  • 这不是一个好主意.. 检查这个库this
  • 这不是仅出于测试目的而修改组件本身的好方法。您最好尝试在测试中模拟上下文。
  • @ArupRakshit 那个 api 似乎使用旧的上下文,而不是 React 16.3 中的新上下文
  • 目前还不清楚在您定义ChildComponent 的地方导入Provider 有什么问题,特别是如果这是出于测试目的。
  • @estus 在我的情况下,问题是这个 Provider 不配合 Enzyme 的 mount 功能(产生错误)。也就是说,答案可能是“无法确定我们是否在上下文提供者中”。

标签: reactjs


【解决方案1】:

没有提供官方方法来检查&lt;Consumer&gt;child是否有&lt;Provider&gt;parent。

一般情况下,&lt;Consumer&gt;&lt;Provider&gt; 内部或外部,undefined 值是没有区别的,两种情况下都会提供undefined 值。

可以使用内部_currentValue 属性检查当前上下文值,但这可能会导致undefined 上下文值的误报:

const ChildComponent = () => {
  if (NameConsumer._currentValue !== undefined) {
    // inside Provider
    return <NameConsumer>
      {context => <span>{context.name}</span>}
    </NameConsumer>
  } else {
    // no provider available, e.g. in a test file
    return <span>Test Text</span>
  }
}

请注意,这在异步渲染中可能无法按预期工作,因此不建议依赖内部。更好的方法是检查测试环境。

更可测试的方法是始终使用NameContext.Consumer 而不是NameConsumer,因此Consumer 属性可以在测试中被模拟。否则,这可能需要模拟一个定义了NameConsumer 的模块。

【讨论】:

    【解决方案2】:

    只需检查上下文。如果未定义,则没有 Provider。

    const myContext = useContext(theContext);
    
    if ( myContext ) {
      return <div>I have a provider.</div>
    }
    
    return <div>I have no provider.</div>
    

    我通常将它用于我想独立工作并成为更大小部件的一部分的组件。在我想提升地图上下文的地方查看类似 Google Maps 的内容。

    const __mapContext = useContext(MapContext);
    
    if ( __mapContext ) {
      return <GoogleMap {...props} />
    }
    
    return (
      <GoogleMapProvider>
        <GoogleMap {...props} />
      </GoogleMapProvider>
    );
    

    【讨论】:

      猜你喜欢
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-06
      • 1970-01-01
      • 2022-08-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多