react query 사용기

otter·2022년 6월 22일
0

Overview

이번 프로젝트에서는 react-query를 사용해보기로 했다.
왜 사용하기로 했냐면 저번 recoil을 사용할때 suspense가 멋지게 동작하고 캐시처리 까지 해줘서 였던 것 같은데(react-query도 이 두가지 기능을 다 가지고 있으니까) 공식문서를 슥 훑어보니 이거 당장 사용할 수 있겠는데? 그런 생각도 들었기 때문이다. 물론 절반은 맞고 절반은 틀렸다. 기본적인 기능은 사용하기 쉬웠으나, 제공하는 기능이 너무 많으니

useQuery

 const { status, data } = useQuery('auth', authFetcher, {
   // 그냥 이렇게만 해도, status에 loading, erroer, succes가 담겨져 있다.
   // data는 전달받은 데이터가 담겨져 있다.
    refetchOnWindowFocus: false,
    retry: false,
  });

  if (status === 'loading') {
    return <LoginLoading />;
  }
  if (status === 'error') {
    return <LoginError />;
  }

  if (status === 'success') {
    navigate('/issues');
  }

위만 보면 아주 쉽다. 단순히 저렇게 해줘서 Fetcher 뒤의 객체는 옵션이니까 그냥 넘어간다고 치고, 현재 loading상태인지 error인지, success인지 확인할 수 있다.
그리고 그에 따른 분기처리도 가능하다. 예전에, useEffect 를 통해서 fetch를 직접 불러왔을 때는 내가 따로 설정해줘야 했던 상태들도 안만들어도 된다.

그런데, 사실 이렇게 만들면 안된다. 이렇게 만들면, 매번 페치함수를 따로 만들어줘야하는 불편함이 있다. 또한, 공식문서의 테스트 가이드를 따르면 react-query 테스트를 위해서는 커스텀 훅으로 변환시켜주어야 한다. 한번하면 될일을 두번하지 말고 처음부터, 커스텀훅으로 만들어 놓자. 애초에 공식문서에서도 커스텀훅을 만들어주고 있으니까.

type ParsedQueryType =
  | string
  | ParsedQs
  | string[]
  | ParsedQs[]
  | undefined
  | null;

type JwtToken = { jwt: string };
type ReadonlyJwtToken = Readonly<JwtToken>;

const fetchAuth = async (code: ParsedQueryType): Promise<ReadonlyJwtToken> => {
  const response = await fetch(
    `auth URL ${code}`,
  );
  if (!response.ok) {
    throw new Error('response not ok');
  }

  return response.json();
};

export const useAuthQuery = (code: ParsedQueryType) =>
  useQuery(['auth', code], () => fetchAuth(code));

이런 방식으로, 쿼리들을 모아서 관리한다면 타입지정도 편하고 어디서 쿼리했는지 알기 편할 것이다. 사실 테스트 코드를 짜려고 커스텀훅을 만들고 있었는데, 이렇게 미리 관리를 안하고 있으니까 어디서 쿼리를 부르고 있는지 확인하기 어려웠다.

종속 쿼리

근데, 위의 쿼리를 실행한 다음에 바로 실행할 쿼리가 있다. 이어서 실행하는 쿼리는 enable 옵션을 통해서 작성할 수있다. 위의 쿼리를 바로 다음에 실행할 커스텀 훅을 작성해 주었다.

export const useIssueQuery = (token: Readonly<string>, enable?: boolean) =>
  useQuery(['issues', token], () => fetchIssues(token), {
    refetchOnWindowFocus: false,
    retry: false,
    enabled: enable,
  });
// jwttoken을 받고 필요한, 그 토큰을 헤더에 담아 issue목록을 요청하는 함수다.
// enabled 옵션을 필요할 경우에 사용하기 위해 넣어주었고,

결과적으론 이렇게 썼다.

  const { status, data: token } = useAuthQuery(code);
// auth 쿼리가 실행되고 data가 받아졌다면,
  const jwtToken = token?.jwt;
  const issues = useIssueQuery(jwtToken, !!jwtToken);
// useIssueQuery는 그 token을 매개변수로 쿼리를 시작한다.
// 여기서 두번째 매개변수가 enable를 작동하는 부분인데
// !!를 통해서 값이 있으면 true로 변환하도록 했다.

결과적으로 이렇게, 위의 쿼리가 실행되고 난 다음에 아래있는 이슈쿼리가 잘 동작했다.
근데, 이런 방법을 굳이 사용하는 이유가 있나? 그런 생각도 들었다.
그냥 success일 경우에 실행하도록 해도 되지 않나? 너무 명령적인가..? 아무튼 공식문서에 나와있는 내용이니까 이를 기반으로 작성했다.

prefetch

아 이거, 예전에 주절주절 어떻게 써놨던 부분이었는데 nextJS를 공부하고 보니 잘못된 내용이 들어가 있어서 후다닥 수정했다. nextJS 를 사용할때 ssg 를 위해 prefetch 할때 사용하는 훅이구나 하고 넘어가면 될 것 같다. 어떻게보면 swr 이 조금 더 편해보이긴 한데, 비슷하다.

결론

쉬운데 어려웠다. 기본적인 기능은 사용하기 아주 쉬웠는데 점차 파고드니 내용이 너무 많고 너무 많은 좋은 기능을 제공하고 있었다. 아마 공부하다 보면 또 거의 쓰는 거만 쓰겠지만! 근데 계속 공부해보고 싶은 라이브러리다.

profile
http://otter-log.world 로 이사했어요!

0개의 댓글