reactjs React JS:找出组件是否在上下文提供程序中

34gzjxbg  于 2023-05-22  发布在  React
关注(0)|答案(3)|浏览(200)

我使用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>
  }
}

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

4smxwvx5

4smxwvx51#

没有提供官方的方法来检查<Consumer>子节点是否有<Provider>父节点。
一般情况下,<Consumer><Provider>内部或外部的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的模块。

z9zf31ra

z9zf31ra2#

看看上下文。如果未定义,则没有Provider。

const myContext = useContext(theContext);

if ( myContext ) {
  return <div>I have a provider.</div>
}

return <div>I have no provider.</div>

我通常使用它的组件,我想独立工作,并成为一个更大的小部件的一部分。看到类似谷歌Map的东西,我想提升Map上下文。

const __mapContext = useContext(MapContext);

if ( __mapContext ) {
  return <GoogleMap {...props} />
}

return (
  <GoogleMapProvider>
    <GoogleMap {...props} />
  </GoogleMapProvider>
);
mgdq6dx1

mgdq6dx13#

您可以为上下文设置类似对象的默认值(为了安全起见,不是原始值或null):

export const someContextDefValue = {}
export const someContext = createContext(someContextDefValue)

现在你可以检查context value了:

const someContextValue = useContext(someContext)
if (someContextValue === someContextDefValue) {
    // Non under context
} else {
    // Context provider detected
}

它将工作,因为我们必须设置值为上下文提供程序(<someContext.Provider value={currentContextValue}>),但新对象的值不等于默认值

相关问题