useContext为什么不需要Context.Provider就能工作?

6

你能解释一下为什么如果我不使用Context.Provider包装组件,useContext()还是能够正常工作吗?我只是将“createContext(someValues)”的结果与预定义的值导出,并在组件中调用useContext(exportedContext),它就可以工作了。每个教程都告诉我要包装组件,React有什么变化吗?


它能够工作,但是你得到的值是“未定义”的,我猜这是在开发体验和尽可能避免应用在生产环境中崩溃之间的一种妥协。 - Jakub Kotrs
你说的"undefined"是什么意思?我可以通过useContext钩子从上下文中成功读取预定义的值。 - FoxNet
哦,对了,我只考虑了没有默认值的createContext(),它会返回undefined - Jakub Kotrs
我认为这从未改变过,只是在不使用包装组件的情况下使用上下文有点无用,你可以直接导出常量并在其他地方导入它,而不必首先使用上下文。 - Jakub Kotrs
@JakubKotrs 这并不是无用的。想一想:上下文保存了一些值,并使用合理的默认值进行初始化。在组件树的某个地方,您希望使用这些默认值,所以只需使用 useContext。而当您希望它们根据某些行为动态更改时,您可以将该子树包装在提供新 valueContext.Provider 中(覆盖默认值)。在 React 中,上下文不仅是状态管理机制,更像是依赖注入机制。如果您希望它成为状态存储,则将树包装在提供程序中,现在它就是一个状态存储。 - avepr
@avepr,你是对的,我也是这样用的,自从我发表了那个评论以来。 - Jakub Kotrs
2个回答

9

所有的消费者组件只要是依赖于某个提供者组件,就会在该提供者组件的 value 属性发生变化时重新渲染。换言之,如果你不使用 Context.Provider 来包裹你的组件,那么当 createContext(someValues) 中的 someValues 发生变化时,这些组件就不会被重新渲染。你只能在第一次渲染时得到设置的初始值。

示例可以在这里查看。


嗨,谢谢你的回答。你确定吗?因为我看到,如果我改变上下文值,它并不会重新渲染。唯一重新渲染的方法是使用setState方法将其放入上下文值状态中。 - FoxNet
这是我为您准备的演示示例:https://codesandbox.io/s/react-context-provider-example-hl4e4f 希望能对您有所帮助 :) - Othmani Ali
1
很棒的答案!当涉及到类和函数组件之间的差异缩小时,我们需要更多这样的快速示例。 - Mike Bendorf

5

React.Context 总是以这种方式工作。

如果一个组件没有被包装在 Context.Provider 中,它将会接收到在创建上下文时设置的默认值。

Provider 的工作是覆盖默认值,从本质上为 React 组件树提供依赖注入机制。

这里有来自 React 团队的好答案:https://github.com/facebook/react/issues/17912


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接