【问题标题】:useContext with React Hooks使用 React Hooks 的 useContext
【发布时间】:2020-05-05 09:02:01
【问题描述】:

我正在关注 YouTube 上关于 useContext 的(视频)教程

从遗留的道具流切换到这个,我有点困惑 ProviderWrapper 中的孩子是什么以及为什么需要传入它。

如果 children 是 SomeComponent2,为什么 someObj 不使用 useContext 就不会单独作为一个 prop 出现?因为它是 ProviderWrapper 的包装器,它通过它的值传递它?

const SomeContext = createContext()

function ProviderWrapper ({children}) {
    const someObj = { 'something': 'someValue' }
    return <SomeContext.Provider value={{ someObj }}>{children}</SomeContext.Provider> 
}

const SomeComponent2 = (props) => {
    console.log('props', props)
    const PropsFromProvider = useContext(SomeContext)
    console.log('PropsFromProvider', PropsFromProvider)
    return null
}

function App() {
    return (
        <ProviderWrapper>
            <SomeComponent2 />
        </ProviderWrapper>
    );
}

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    children 这里的意思是渲染&lt;ProviderWrapper&gt; 标签之间传递的任何内容,在你的情况下是&lt;SomeComponent2 /&gt;

    就您对 someObj 可用作 SomeComponent2 的道具的想法而言,您不应该将 {someObj} 传递给 &lt;SomeContext.Provider&gt; 的 value 道具,您必须将其视为保存数据的组件和当您使用useContext 时,它会将该数据提供给使用它的组件

    如果您使用 redux,可以将其视为类似于 react-redux 中的 Provider 组件。在 redux 中访问组件中的任何 redux 值,您使用 connectmapStateToPropsuseContext 在这里扮演类似的角色

    上述逻辑的实现可以在没有上下文的情况下完成,但使用渲染道具,以便 SomeComponent2 传递 someObj 作为道具,如下所示

    function ProviderWrapper ({children}) {
        const someObj = { 'something': 'someValue' }
        return children({someObj}); 
    }
    
    const SomeComponent2 = (props) => {
        console.log('props', props)
        return null
    }
    
    function App() {
        return (
            <ProviderWrapper>
                {(props) => <SomeComponent2 {...props}/>}
            </ProviderWrapper>
        );
    }
    

    但上述逻辑的局限性在于它只能将道具直接传递给孩子。为了访问嵌套级别中的道具,您需要将它们一直向下传递。

    【讨论】:

    • 如果以上帖子对您有帮助,请告诉我。
    【解决方案2】:

    从 reactJS 文档中,useContext 从最近的上下文提供者获取值。 通常他们做的是

    // You create a context
    const SomeContext  = createContext();
    
    // Then you wrap any component that need the value in it provider
    <SomeContext.Provider value={{'something': 'someValue'}}>
        //Your component
    </SomeContext.Provider>
    
    // In any Your Component, You access the value by using useContext
    function YourComponent() {
        const value = useContext(SomeContext);
    
        console.log(value); //You will get the Obj
        // It is not pass as Props
        ...
    }
    

    ProviderWrapper 只是一个包装器,因此您可以包装任何可以访问 SomeContext 的组件,因此您无需继续编写

    <SomeContext.Provider value={{}}>
        //Your Component
    </SomeContext.Provider>
    

    希望这是有道理的,并回答您的问题。 如果我错了,请纠正我

    【讨论】:

    • 如果我不编写返回 的包装器,那么 useContext(SomeContext) 有什么意义,因为 SomeContext 中没有设置和传递值?
    • 对不起,这只是一个例子。
    【解决方案3】:

    从遗留的道具流切换到这个,我有点困惑 ProviderWrapper 中的孩子是什么以及为什么需要传入它。

    children 是您在&lt;ProviderWrapper&gt; ...children... &lt;/ProviderWrapper&gt; 中呈现的任何子组件。所以在这个例子中,是的,它是&lt;SomeComponent2 /&gt;

    如果 children 是 SomeComponent2,为什么 someObj 不使用 useContext 就不会单独作为一个 prop 出现?因为它是 ProviderWrapper 的包装器,它通过它的值传递它?

    它可以 - 你可以只渲染&lt;SomeComponent2 something={somevalue} /&gt;。这将是通常的做法。

    然而,本教程试图展示的是 Context 如何允许您访问父组件中的值,而无需通过 props 传递它们。在这个例子中,这是微不足道的,但想象一下如果“somevalue”在更高的层次上,并且每个组件都在不同的文件中渲染另一个组件。您必须将值一直向下传递到许多组件,将 something 属性添加到每个组件。这称为“prop-passing”或“prop-drilling”,它意味着添加组件不需要的 props,只是为了将它们传递给最终需要它们的组件。

    使用 Context,您只需在更高的某个方便的位置渲染一个 Provider,树中任何位于其下方的任何组件,在任何深度,都可以使用它的值。这对于定义主题(例如“浅色”或“深色”)等事情很有用,这样组件就可以适当地呈现自己,而无需将“主题”作为道具添加并一直向下传递。

    【讨论】:

      猜你喜欢
      • 2020-10-11
      • 1970-01-01
      • 2020-01-27
      • 2021-06-16
      • 1970-01-01
      • 2020-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多