source

너무 많은 리액트 컨텍스트 제공자

gigabyte 2023. 4. 4. 21:22
반응형

너무 많은 리액트 컨텍스트 제공자

새로운 Context API에 대해 고민하고 있습니다(Redux 등에 대해서는 아직 조사하지 않았습니다).

내가 해야 할 일의 대부분은 할 수 있을 것 같지만, 결국 메인 앱을 포장하기 위해 태그가 필요한 수많은 프로바이더와 함께 하게 될 것이다.

Auth 프로바이더, Theming 프로바이더, 채팅 메시지 프로바이더(Pusher.com 참조)를 준비합니다.또한 React Router를 사용하는 것도 래퍼 요소입니다.

결국 이것(그리고 더 많은 것)으로 끝나야 하나요?

<BrowserRouter>
    <AuthProvider>
        <ThemeProvider>
            <ChatProvider>
                <App />
            </ChatProvider>
        </ThemeProvider>
    </AuthProvider>
</BrowserRouter>

아니면 더 좋은 방법이 있을까요?

서드파티 라이브러리가 없는 프로바이더를 위한 솔루션을 원하는 경우 Typescript 주석이 있는 솔루션을 다음에 제시합니다.

// Compose.tsx

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

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

    return (
        <>
            {components.reduceRight((acc, Comp) => {
                return <Comp>{acc}</Comp>
            }, children)}
        </>
    )
}

사용방법:

<Compose components={[BrowserRouter, AuthProvider, ThemeProvider, ChatProvider]}>
    <App />
</Compose>

Typescript를 사용하지 않으면 주석을 제거할 수 있습니다.

솔루션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;
}

사용방법:

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

@rista404의 답변을 사용합니다(https://stackoverflow.com/a/58924810/4035).
~하듯이react-context-composer는 권장되지 않습니다.

@AO17님, ping 감사합니다.


면책사항:이걸 써본 이 없어 그냥 조사했을 뿐이야.

많은 OSS 프로젝트에 공헌하고 있는 Freadable Labs에는 react-context-composer라는 프로젝트가 있습니다.

이것으로 당신의 문제가 해결된 것 같습니다.

React가 새로운 Context API를 제안하고 있습니다.API는 작곡을 장려합니다.이 유틸리티 컴포넌트는 컴포넌트가 여러 컨텍스트프로바이더와 컨슈머를 렌더링 할 때 코드를 깨끗하게 유지하는 데 도움이 됩니다.

몇 줄의 코드가 문제를 해결합니다.

import React from "react"
import _ from "lodash"

/**
 * Provided that a list of providers [P1, P2, P3, P4] is passed as props,
 * it renders
 *
 *    <P1>
        <P2>
          <P3>
            <P4>
              {children}
            </P4>
          </P3>
        </P2>
      </P1>
 *
 */

export default function ComposeProviders({ Providers, children }) {
  if (_.isEmpty(Providers)) return children

  return _.reverse(Providers)
    .reduce((acc, Provider) => {
      return <Provider>{acc}</Provider>
    }, children)
}

이를 위한 간단한 해결책 중 하나는 Redux가 사용하는 것과 같은 구성 함수를 사용하여 모든 공급자를 결합하는 것입니다.그러면 compose 함수는 다음과 같이 호출됩니다.

const Providers = compose(
    AuthProvider,
    ThemeProvider,
    ChatProvider
);

또한 저는 이 솔루션을 사용하지 않았지만 React의 새로운 후크 기능을 사용하여 컨텍스트를 렌더링하는 대신 리액트 후크를 사용하여 함수 정의에서 액세스할 수 있습니다.

프로바이더 elemet에 외부 소품을 삽입해야 하는 경우 js nest helper를 재구성합니다.

코멘트는 없지만 컴포넌트를 정리한rista404 답변을 통합하면 도움이 될 수 있습니다.useCallback()훅을 사용하여 페이지 전환과 같은 경우에 컨텍스트 데이터 무결성을 보장합니다.

// Compose.tsx

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

const Compose = useCallback((props: Props) => {
    const { components = [], children } = props

    return (
        <>
            {components.reduceRight((acc, Comp) => <Comp>{acc}</Comp>, children)}
        </>
    )
}, [])

export default Compose

언급URL : https://stackoverflow.com/questions/51504506/too-many-react-context-providers

반응형