React Context Wrapper

곰튀김·2023년 8월 9일
0
post-thumbnail

Goal

  • React App 에서 전역으로 사용할 공용 state 관리가 필요하다
  • context 를 사용하면 별도의 라이브러리가 필요없으니 좋겠다
  • 사용하기 불편하니까 편하게 쓰고 싶다

Interface

  • 설정은 이렇게 (심플하게)
<AppStateProvider>
  <App/>
</AppStateProvider>
  • 사용할 때는 이렇게 (useState 처럼)
const [lang, setLang] = useAppState('lang', 'en');

return (
  <>
    <p>{lang}</p>
    <button onClick={() => setLang(() => 'ko')}>KO</button>
    <button onClick={() => setLang(() => 'en')}>EN</button>
  </>
  );
}
  • initial state 를 지정할 수 있으면 좋겠다.
  • 미리 지정하지 않아도 하위 컴포넌트가 필요에 따라 추가할 수 있도록.

Implementation

  • createContext 하고나서 외부에 노출시키지 말자. 내부에서 알아서 하자.
  • appContext 는 export 하지 않는다.
const appContext = createContext({});

export default function AppStateProvider() {
  return (
    <appContext.Provider value={}>
      {props.children}
    </appContext.Provider>
  );
}
  • 그러면 appContext를 사용하는 hook 도 같은 파일에 넣자.
export function useAppState(keyName: string, defaultValue: any) {
  ...
  return [_state, _setState];
}
  • Provider 차원에서 state 하나를 가지고 제공되게 하자.
  • state 변경이 필요하면 Provider의 state값을 바꾸게 하자.
  • 그러면 state를 변경할 수 있는 함수도 value에 함께 전달해줘야 한다.
export default function AppStateProvider() {
  const [appState, setAppState] = useState({});

  return (
    <appContext.Provider
      value={{
        state: appState,
        setState: (update: any) => setAppState(update)
      }}
    >
      {props.children}
    </appContext.Provider>
  );
}
  • 하위 컴포넌트에서 useAppState 를 사용할 때는 전체 state가 아니라 필요한 부분만 얻을 수 있도록 하자.
  • 변경할 때도 해당 일부만 업데이트 되도록 하자
const { state, setState } = useContext(appContext);

// keyName 에 해당하는 값을 뽑아서 주자
const _state = state[keyName] ?? defaultValue; // 필터링
const _setState = (f: (s: any) => any) => {
  setState({ ...state, [keyName]: f(_state) }); // 업데이트
};

return [_state, _setState];
  • 단순하게 값을 읽어오기만 하는 hook 도 만들자.
export function useAppStateValue(keyName: string) {
  const { state } = useContext(appContext);
  return state[keyName]; // keyName 에 해당하는 값만
}
  • initial 값을 지정할 수 있게 하자
export default function AppStateProvider({initialState}) {
  const [appState, setAppState] = useState(initialState);
  ...
}

Source Code

profile
사실주의 프로그래머

1개의 댓글

comment-user-thumbnail
2023년 8월 9일

Context API로 직접 만들어보면 확실히 좋은 것 같아요! 디자인 패턴을 구현할 때 써봐도 좋기도 하구요 ㅎㅎ 잘 보고갑니다 :)

답글 달기