ABOUT ME

생각 많은 스타트업 개발자의 고군분투 인생기를 담아갑니다.

Today
Yesterday
Total
  • [React / React Native] 각종 Provider들의 역할
    만들기 2019. 11. 27. 13:21

    현재 진행중인 React Native 프로젝트 개발 환경을 세팅하던 중, 문득 React를 하다보면 자주 볼 수 있는 Provider들이 어떤 역할을 하는지 궁금해져서 잠깐 정리 해봤습니다.

    우선 styled-components 에서 사용하는 ThemeProvider부터 살펴보면

    export interface DefaultTheme {}
    
    export interface ThemeProviderProps<T extends object, U extends object = T> {
        children?: React.ReactNode;
        theme: T | ((theme: U) => T);
    }
    export type BaseThemeProviderComponent<
        T extends object,
        U extends object = T
    > = React.ComponentClass<ThemeProviderProps<T, U>>;
    export type ThemeProviderComponent<
        T extends object,
        U extends object = T
    > = BaseThemeProviderComponent<AnyIfEmpty<T>, AnyIfEmpty<U>>;
    export const ThemeProvider: ThemeProviderComponent<AnyIfEmpty<DefaultTheme>>;
    // NOTE: this technically starts as undefined, but allowing undefined is unhelpful when used correctly
    export const ThemeContext: React.Context<AnyIfEmpty<DefaultTheme>>;
    export const ThemeConsumer: typeof ThemeContext["Consumer"];
    

    생각보다 별게 없네요 ㅎㅎ;;

    그럼 다음은 apollo-client 에서 사용하는 ApolloProvider

    import React from 'react';
    import ApolloClient from 'apollo-client';
    export interface ApolloProviderProps<TCache> {
        client: ApolloClient<TCache>;
        children: React.ReactNode | React.ReactNode[] | null;
    }
    export declare const ApolloProvider: React.FC<ApolloProviderProps<any>>;
    

    역시 코드가 길지 않습니다.

    둘이 하는 역할이 동일하고, 단순히 원하는 타입의 Props를 받아서 children 에게 전파하는 역할만 담당하게 됩니다.

    실제 사용하는 코드를 보면,

    // 여러 파일에서 일부분만 복붙한 코드입니다. 그냥 쓰시면 동작하지 않습니다 ㅠㅠ
    interface IProps {
      initialThemeType?: ThemeType;
      children?: React.ReactElement;
    }
    
    function CustomApolloProvider({
      initialThemeType,
      children
    }: IProps): React.ReactElement {
      const { state } = useAppContext()
      let token: string | undefined = undefined
      if (state.user && state.user.token) token = state.user.token
      return <ApolloProvider client={getClient(token)}>{children}</ApolloProvider>
    }
    
    function CustomThemeProvider({
      children,
      initialThemeType = defaultThemeType,
    }: Props): React.ReactElement {
      const [themeType, setThemeType] = useState(initialThemeType);
      const changeThemeType = (): void => {
        const newThemeType =
          themeType === ThemeType.LIGHT ? ThemeType.DARK : ThemeType.LIGHT;
        setThemeType(newThemeType);
      };
      const theme = createTheme(themeType);
    
      return (
        <Provider
          value={{
            changeThemeType,
            themeType,
            theme,
          }}
        >
          <ThemeProvider theme={theme}>{children}</ThemeProvider>
        </Provider>
      );
    }
    
    const RootProviders = ({
      initialThemeType,
      children
    }: Props): React.ReactElement => {
      return (
        <AppProvider>
          <CustomThemeProvider
            initialThemeType={
              initialThemeType === ThemeType.LIGHT ? ThemeType.LIGHT : undefined
            }
          >
            <CustomApolloProvider>{children}</CustomApolloProvider>
          </CustomThemeProvider>
        </AppProvider>
      );
    };
    
    export default RootProviders;

    이런 식으로 자식 컴포넌트 안에서 apolloClient / theme 속성을 사용할 수 있게 해줍니다.

     

    [맘먹고 정리 하려다가 생각보다 별게 없어서 허무하게 끝난 포스팅....]

     

    댓글

Designed by Tistory.