React Context提供者过多

jon*_*bbs 8 reactjs react-context

在这里做出反应并尝试将新的Context API包裹住(我还没有研究Redux等)。

似乎我可以做很多我需要做的事情,但是最终我将得到很多提供程序,所有提供程序都需要一个标签来包装我的主应用程序。

我将要为Auth提供一个提供程序,一个为主题提供程序,一个为聊天消息提供程序(通过Pusher.com访问),等等。另外使用React Router的是另一个包装元素。

我要结束这个(还有更多)吗?

<BrowserRouter>
    <AuthProvider>
        <ThemeProvider>
            <ChatProvider>
                <App />
            </ChatProvider>
        </ThemeProvider>
    </AuthProvider>
</BrowserRouter>
Run Code Online (Sandbox Code Playgroud)

或者,还有更好的方法?

ris*_*404 37

如果您想要一种无需任何第三方库即可组合 Providers 的解决方案,这里有一个带有 Typescript 注释的解决方案:

// Compose.tsx

interface Props {
    components: Array<React.JSXElementConstructor<React.PropsWithChildren<any>>>
    children: React.ReactNode
}

export default function Compose(props: Props) {
    const { components = [], children } = props

    return (
        <>
            {components.reduceRight((acc, Comp) => {
                return <Comp>{acc}</Comp>
            }, children)}
        </>
    )
}
Run Code Online (Sandbox Code Playgroud)

用法:

<Compose components={[BrowserRouter, AuthProvider, ThemeProvider, ChatProvider]}>
    <App />
</Compose>
Run Code Online (Sandbox Code Playgroud)

如果您不使用 Typescript,您当然可以删除注释。

  • 如何将“value”属性传递给“compose”内的上下文提供者? (6认同)
  • 当提供者需要时添加属性:const { Components = [], Children, ...rest } = props。......返回 &lt;Comp {...rest}&gt;{acc}&lt;/Comp&gt; (4认同)

小智 6

for循环的解决方案:

export const provider = (provider, props = {}) => [provider, props];

export const ProviderComposer = ({providers, children}) => {
    for (let i = providers.length - 1; i >= 0; --i) {
        const [Provider, props] = providers[i];
        children = <Provider {...props}>{children}</Provider>
    }
    return children;
}
Run Code Online (Sandbox Code Playgroud)

用法:

<ProviderComposer
    providers={[
        provider(AuthProvider),
        provider(ThemeProvider),
        provider(MuiPickersUtilsProvider, {utils: DateFnsUtils}),
    ]}
>
    <App/>
</ProviderComposer>
Run Code Online (Sandbox Code Playgroud)