본문 바로가기
개발 Study/React

[React/Recoil] React-Query + Recoil로 SessionStorage에 상태 값 저장하기

by jiyoon_92 2023. 4. 7.
반응형

Recoil 로고

React-Query + Recoil 을 사용하여 SessionStorage에 상태 값 저장하기

 

React-Query로 비동기 API 통신으로 얻은 값을 Recoil을 사용하여 저장하지만, 새로고침을 클릭할 경우 값이 날아갈 수 있다. 이런 경우, SessionStorage나 LocalStorage에 저장하여 값을 유지할 수 있는데 오늘은 SessionStorage에 저장하는 방법을 알아보자.

2023.04.04 - [개발 Study/React] - [React/Recoil] Recoil 을 상태관리 라이브러리로 선택한 이유

 

[React/Recoil] Recoil 을 상태관리 라이브러리로 선택한 이유

상태관리 라이브러리로 Recoil 을 선택하다. 1. Recoil 이란? Recoil은 Facebook(현 Meta)에서 개발한 React 애플리케이션용 상태 관리 라이브러리다. Atom 및 Selector의 개념을 도입하여 응용 프로그램의 상태

chuun92.tistory.com

반응형

1. 상태 값 Atom으로 생성하기

recoil폴더 내에 필요한 상태 값을 저장할 .ts 파일을 생성하고, 아래와 같이 예시로 작성한다.

recoil 경로

export const oneAccountState = atom<IOneAccountInfo>({
  key: "oneAccountState",
  default: {
    oneToken: "",
    uid: -1,
    mid: -1,
    name: "",
    handphone: "",
    pwYN: "N",
    termsYN: "Y",
    status: "Y",
    jsonData: [],
    resYN: "N",
    resCode: -1,
    resMsg: "",
  },
  effects: [
    ({ onSet }) => {
      onSet((newValue, oldValue, isReset) => {
        isReset
          ? sessionStorage.removeItem("oneAccountState")
          : sessionStorage.setItem("oneAccountState", JSON.stringify(newValue));
      });
    },
  ],
});

 

 

IOneAccountInfo Interface를 타입으로 갖는 로그인 상태를 Atom으로 생성한다. 코드를 살펴보면, key 값을 string으로 갖고있고 저 key값으로 스토리지에 상태 값이 저장된다. default 옵션으로 초기 값을 지정해놓을 수 있다. effects에서  atom 변경 시 부수적으로 실행되는 함수가 있는데 onSet()함수다. 파라미터로 newValue, oldValue, isReset을 받는데 초기화인 경우 sessionStorage에서 'oneAccountState' 키 값을 갖는 아이템을 지워주고, 아닌 경우 새로 받은 값을 stringify해서 'oneAccountState'에 넣어준다.


2. React-Query로 useMutation 훅 생성하기

mutation은 파라미터를 받아서 mutationFn(함수)을 실행시키고 실행시켜 받아온 값을 return해 준다. 보통 데이터를 생성, 삭제, 변형 등을 할 때 사용되는 훅이다.

보통 React 에서 훅은 function component 내에서만 선언이 가능하며, mutation만 따로 빼서 관리를 해주고 싶은 경우, function으로 한 번 더 감싸서 custom hook 형태로 만들어주면 된다.

mutation 경로

CustomHook 내에서 mutation도 사용하고, API 통신에서 나온 결과 값을 recoil로 한번에 저장해주기 위해 아래와 같이 코드를 구현했다.

export const oneAuthMutation = () => {
  const setOneAccountState = useSetRecoilState(oneAccountState);
  return useMutation<IOneAccountInfo, AxiosError, IOneLoginInput, any>({
    mutationFn: async (input) => {
      return axios({
        method: "post",
        url: `${baseURL}/Auth`,
        headers: {
          "Content-Type": "application/x-www-form-urlencoded",
        },
        data: input,
      }).then((response) => {
        return response.data;
      });
    },
    onError: (err) => {
      console.log(err);
    },
    onSuccess: (data: IOneAccountInfo, args) => {
      setOneAccountState(data);
    },
  });
};

 

`useSetRecoilState`는 상태 값을 저장하기 위해 사용하는 훅으로, 상태를 읽어올 순 없고 값을 저장할때만 쓸 수있다.

1번에서 생성한 oneAccountState에 저장하기 위해 setOneAccountState를 선언한다. 그리고 useMutation 훅을 return해주는데 useMutation 안을 살펴보자. 우선 Typescript 를 사용하기 때문에 <> 내에 <data로 받아오는 타입, error가 발생했을 경우 return되는 타입, mutationFn에 parameter로 들어가는 타입, context 타입> 으로 설정해주면 된다.

mutationFn에서 실행시킬 api 호출 함수를 넣어준다. axios 라이브러리를 활용하여 비동기 통신을 연결해주고 post방식으로 통신한다. onError()는 에러가 났을 경우 실행되는 코드를 넣어준다. onSuccess()에서는 mutation 성공 시 recoil로 상태값이 저장되도록 setOneAccountState()에 데이터를 넣어준다.


3. Mutation 실행하기

로그인 페이지에서 id/pw 입력 후 로그인 버튼을 누르면 onSubmit 함수가 실행되고 그 안에서 recoil로 로그인정보도 저장하고, 인증 api도 실행시킨다.

function Login() {
  const authMutation = oneAuthMutation(); // 로그인 Mutation
  const [loginInput, setLoginInput] = useRecoilState(oneLoginState);
  
  /*form관련 validation함수 생략*/
  const onSubmit = async (data: IOneLoginInput) => {
    data.appType = "W";
    setLoginInput(data); // 로그인 정보 저장
    authMutation.mutateAsync(data); // Auth API 실행
  };
  
  return (
    <>
      <GlobalStyle />
      <Wrapper>
        <div className="register-form">
          <Form onSubmit={handleSubmit(onSubmit)}>
            {/* <HeaderImg /> */}
            <div className="form-group">
              <Input
                type="text"
                {...register("userId")}
                className={`form-control ${errors.userId ? "is-invalid" : ""}`}
              />
              <div className="invalid-feedback">{errors.userId?.message}</div>
            </div>
            <div className="form-group">
              <Input
                type="password"
                {...register("userPw")}
                className={`form-control ${errors.userPw ? "is-invalid" : ""}`}
              />
              <div className="invalid-feedback">{errors.userPw?.message}</div>
            </div>
            <Button disabled={isSubmitting}>로그인</Button>{" "}
            {/* isSubmitting : 제출 끝날 때까지 버튼 비활성화 */}
          </Form>
        </div>
      </Wrapper>
    </>
  );
}

 

useRecoilState로 로그인 정보를 저장하거나 읽을 수 있다. 2번에서와 다르게 읽고쓰기가 가능하도록 하는 훅이다. 로그인 시 제출되는 정보를 oneLoginState에 담기 위해 setLoginInput()함수에 제출된 data를 넣어준다. 그리고 제출된 data로 2번에서 작성한 인증용 muation을 실행시킨다.

 

SessionStorage 저장 결과

mutation이 성공적으로 실행되면 위와 같이 SessionStorage에 저장된다.

 

반응형

댓글