토큰 갱신, 유저 정보 불러오기 custom hook

이승민·2021년 11월 12일
0

기록용으로 올리는 react-query, recoil, typescript를 사용한 custom hook

유저 정보 불러오기 custom hook

import { AxiosError, AxiosResponse } from "axios";
import { useQuery } from "react-query";
import { useRecoilValue } from "recoil";
import { getUserInfo } from "src/api/auth";
import { userState } from "src/recoils/atoms/auth";
import { ErrorCode, LocalStorageKey, CookieKey } from "src/types";
import useHandleRefresh from "./useHandleRefresh";
import { getCookie } from "./useCookie";

export default function useGetUserInfo() {
  const userInfo = useRecoilValue(userState);
  const handleRefresh = useHandleRefresh();
  return useQuery(
    ["userInfo", userInfo?.id],
    () => getUserInfo(userInfo, localStorage.getItem(LocalStorageKey.access_token)),
    {
      keepPreviousData: true,
      retry: false,
      cacheTime: Infinity,
      staleTime: 10000,
      onError: (error: AxiosError) => {
        const errorCode = error.response?.data.code;
        if (errorCode === ErrorCode.expire_token) {
          handleRefresh.mutate(getCookie(CookieKey.refresh_token));
        }
      },
    }
  );
}

access 토큰 갱신 custom hook

import axios, { AxiosError, AxiosResponse } from "axios";
import { useMutation, useQueryClient } from "react-query";
import { tokenRefresh } from "src/api/auth";
import { LocalStorageKey, TokenResponse } from "src/types";

export default function useHandleRefresh() {
  const queryClient = useQueryClient();
  const refreshMutation = useMutation(
    (refreshToken: string) => tokenRefresh({ refresh: refreshToken }),
    {
      onSuccess: (res: AxiosResponse<TokenResponse>) => {
        localStorage.setItem(LocalStorageKey.access_token, res.data.access);
        queryClient.invalidateQueries(["userInfo"]);
      },
      onError: (error: unknown | AxiosError) => {
        if (axios.isAxiosError(error)) {
          const errorMsg: string = error.response?.data.message;
        } else {
          throw Error;
        }
      },
    }
  );
  return refreshMutation;
}

user data는 global state에 저장하지 않고 사용하는 컴포넌트에서 useState로 관리한다.

token refresh 이후 이전 작업을 다시 재시도 하도록 queryClient.invalidateQueries() 를 사용한다.

useHandleRefresh hook의 역할은 token을 refresh 하는 것으로 그 이외의 역할은 하지 않는다. ( 예) 에러시 alert 처리 등)

cookie, local storage 등의 key 값은 enum 등을 이용하여 변수화해서 사용하자.

profile
프론트 앤드 개발자를 꿈꿉니다.

0개의 댓글