[React JS] useReducer + useContext

박세화·2023년 6월 19일

React JS

목록 보기
7/22

selectedContext.tsx

import { ReactNode, createContext, useReducer, Dispatch } from "react";

interface SelectedProviderProps {
  children: ReactNode;
}

interface selectedContext {
  ctr: string;
  ndl: string;
  meat: string;
  spc: string;
}

interface actionType {
  type: "add";
  payload: any;
}

export const SelectedContext = createContext({} as selectedContext);

export const DispatchContext = createContext<Dispatch<actionType> | null>(null);

const reducer = (
  state: selectedContext,
  action: actionType
): selectedContext => {
  const { type, payload } = action;
  switch (type) {
    case "add":
      const { value, label } = payload;
      return { ...state, [value]: label };
  }
};

const INITIAL_VALUE: selectedContext = {
  ctr: "",
  ndl: "",
  meat: "",
  spc: "",
};

export const SelectedProvider = ({ children }: SelectedProviderProps) => {
  const [{ ctr, ndl, meat, spc }, dispatch] = useReducer(
    reducer,
    INITIAL_VALUE
  );

  const value: selectedContext = { ctr, ndl, meat, spc };

  return (
    <DispatchContext.Provider value={dispatch}>
      <SelectedContext.Provider value={value}>
        {children}
      </SelectedContext.Provider>
    </DispatchContext.Provider>
  );
};
  • interface로 Provider props, selectedContext, actionType의 타입 정의

  • createContext<Dispatch<actionType> | null>(null)
    1) Dispatch의 generics가 actionType라고 선언
    2) 그리고 Dispatch자체를 context안에 담는다

  • reducer 함수 : 현재 상태와 액션을 파라미터로 갖는다.

  • SelectorProvider 함수)
    useReducer : 현재 상태와 dispatch함수를 반환


selectBox.tsx

const dispatch = useContext(DispatchContext);

<Container fluid="md">
      <label>한식?양식?</label>
      <Select options={ctrOptions} onChange={(e:any) => dispatch({type: "add", payload: e})}></Select>
      <label>??</label>
      <Select options={ndlOptions} onChange={(e:any) => dispatch({type: "add", payload: e})}></Select>
      <label>매운 거 괜찮?</label>
      <Select options={spcOptions} onChange={(e:any) => dispatch({type: "add", payload: e})}></Select>
      {/* optional */}
      <label>고기는?</label>
      <Select options={meatOptions} onChange={(e:any) => dispatch({type: "add", payload: e})}></Select>
      <Button onClick={() => gotoNext("/menu")}>메뉴 추천받기</Button>
</Container>
  • context 안에 담긴 dispatch 를 불러와서 onChange 함수 안에 넣어준다.

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

0개의 댓글