Typescript로 하는 React Context 잡기술

2021. 9. 14. 19:58프로그래밍/Typescript

728x90

오늘도 개발을 하다가 좋은 방법을 발견해서 포스팅을 해본다.


내가 기존에 사용하던 방법

import React, {useState} from 'react';

const PageManageContext = React.createContext<PageManageContextProps>({});
const { Provider, Consumer: PageManageConsumer } = PageManageContext;

const PageManageProvider: React.FunctionComponent = props => {
  const [page, setPage] = useState<string>('memo');

  return (
    <Provider value={{ page, setPage }}>
      {props.children}
    </Provider>
  );
}

export default PageManageContext;
export interface PageManageContextProps {
  page?: string;
  setPage?: React.Dispatch<React.SetStateAction<string>>;
};
export { PageManageProvider, PageManageConsumer };

이런식으로 Context의 Provider를 확장하여 사용하고 있었다.

그런데 이런 코드에서는 문제가 좀 있다.
우선 문제를 파악하기 위해서 코드를 좀 뜯어보자.

// 1. 초기화를 {}로 하였다.
const PageManageContext = React.createContext<PageManageContextProps>({});

// 2. Provider가 PageManageContextProps에 있는대로 전달한다
<Provider value={{ page, setPage }}>

// 3. 초기화 할 때 빈 object를 추가하기 때문에 Interface에 각 propterty는 nullable로 한다.
export interface PageManageContextProps {
  page?: string;
  setPage?: React.Dispatch<React.SetStateAction<string>>;
};

그렇기 때문에 이 property들을 사용하게 되면 nullcheck를 해주게 된다.

const { setPage } = useContext(PageManageContext);

const handleChangePage = (key: string) => {
  if (setPage) {
    setPage(key);
    setDrawerOpened(false);
  }
}

새로운 방법

우선 정리를 하면 다음과 같다

1. createContext를 할 때, type을 XXX | null로 설정하고, null로 초기화 한다.

2. 새로운 Hook을 만들어 null체크를 한 다음 반환한다.

import React, {useState, useContext} from 'react';

const PageManageContext = React.createContext<PageManageContextProps | null>(null);
const { Provider, Consumer: PageManageConsumer } = PageManageContext;

const PageManageProvider: React.FunctionComponent = props => {
  const [page, setPage] = useState<string>('memo');

  return (
    <Provider value={{ page, setPage }}>
      {props.children}
    </Provider>
  );
}

export default PageManageContext;
export interface PageManageContextProps {
  page: string;
  setPage: React.Dispatch<React.SetStateAction<string>>;
};
export { PageManageProvider, PageManageConsumer };
export function usePageManage() {
  const state = useContext(PageManageContext);

  if (!!!state) throw new Error('PageManageContext is Null'); // 유효하지 않을땐 에러를 발생

  return state;
}

포인트를 다시 보자.

// 1. null로 초기화한다.
const PageManageContext = React.createContext<PageManageContextProps | null>(null);

// 2. property는 더이상 nullable이 아니다.
export interface PageManageContextProps {
  page: string;
  setPage: React.Dispatch<React.SetStateAction<string>>;
};

// 3. PageManageContext를 wrap하고 null체크를 한다.
export function usePageManage() {
  const state = useContext(PageManageContext);
  if (!!!state) throw new Error('PageManageContext is Null'); // 유효하지 않을땐 에러를 발생
  return state;
}

이제 이렇게 사용하면 된다.

const { setPage } = usePageManage();

const handleChangePage = (key: string) => {
  setPage(key);
  setDrawerOpened(false);
}

참고 문서

https://react.vlpt.us/using-typescript/04-ts-context.html

 

4. TypeScript 와 Context API 활용하기 · GitBook

4. TypeScript 와 Context API 활용하기 이번에는 TypeScript 와 Context API 를 활용하는 방법을 배워보겠습니다. 이번에 배울 것은 3장의 섹션2 Context API를 활용한 상태관리와 매우 유사합니다. State를 위한 Co

react.vlpt.us

'프로그래밍 > Typescript' 카테고리의 다른 글

실전 TypeScirpt 5  (0) 2021.07.05
실전 TypeScript - 4  (0) 2021.07.04
실전 TypeScript 2  (0) 2021.07.02
근황 & 실전 TypeScript 1  (0) 2021.07.01
TypeScript - Handbook (Modules)  (0) 2021.06.23