[React-Query] fetchQuery vs prefetchQuery

Sming·2023년 10월 23일
12

안녕하세요~ 오늘은 약간 가벼운 주제로 가져오게된 react-query의 fetchQueryprefetchQuery에 대한 내용입니다.

prefetchQuery

보통 Next.js를 이용하여 ssr을 이용하실때 그냥 fetch만으로 이용하시는 경우도 있지만 경우에 따라서 react-query를 사용할 때가 있습니다.

그런 경우 react-query에서는 prefetchQuery라는 메서드를 이용하여 ssr을 사용할 수 있도록 제공합니다.

  const queryClient = getQueryClient();

  await queryClient.prefetchQuery({
    queryKey: ['test'],
    queryFn: getTest
  });

다음과 같이 prefetchQuery를 Next.js 12에서는 getServerSideProps, getStaticSideProps, Next.js 13 (App router) 에서는 server component에서 이용하시면 server에서 미리 데이터를 만들어 놓은 후 이 다음에 fetch하는것에는 이미 완성된 초기 데이터를 이용하는것이죠.

const {data} = useQuery(['test'], getTest);
...

실제 사용할때는 client단에서 prefetchQuery를 이용했던것과 동일한 query key를 설정하시면 됩니다.

이렇게 이용할시 기존에 data가 undefined (pending) -> data (fulfilled) 되던 방식이 undefined가 initial data로 초기화 되있는 상태가 됩니다.

fetchQuery

이제는 fetchQuery에 대해서 얘기해봐야겠죠?

사실 대부분 react-query에서 ssr을 이용할때 prefetchQuery를 이용합니다.
https://tanstack.com/query/v4/docs/react/guides/ssr

docs만 봐도 prefetchQuery로 하는 예시로만 되어있어 보통 이것만 이용하는 경우가 많습니다.


하지만 prefetchQuery는 항상 성공한 쿼리만 dehydrate를 해주게 됩니다. 그리고 성공한 데이터에 대해서 결과값을 return을 하지 않습니다.

반면에 fetchQuery는 실패할 경우 에러를 던지며, 결과값에 대한 return을 할 수 있습니다.

보통 저는 2가지 케이스에서 이용을 합니다.

  • server에서 받은 queryData를 통하여 jotai의 hydrateAtom 초기화
  • ssr에서의 error boundary를 이용할시

⭐️ server에서 받은 queryData를 통하여 jotai의 hydrateAtom 초기화

  const SearchFilter = () => {
    const queryClient = getQueryClient();
  	const searchFilter = await queryClient.fetchQuery({
    	queryKey: ['searchFilter', DEFAULT_SEARCH_FILTER],
    	queryFn: () => getSearchFilter(params),
  	});

    return (
      <HydateAtomProvider atomKey="searchFilterInputAtom" value={searchFilter}>
        <SearchFilterContents data={searchFilter} atomValue={atomValue} />
      </HydateAtomProvider>
    );
  }

⭐️ ssr에서의 error boundary를 이용할시

// HydratedList.tsx

export const HydratedList = async ({ params }: Params) => {
  const queryClient = getQueryClient();
  await queryClient.fetchInfiniteQuery({
    queryKey: ['searchResult'],
    queryFn: () => getList(params),
  });
  const dehydratedSearchResult = dehydrate(queryClient);

  return (
    <Hydrate state={dehydratedSearchResult}>
      <List params={params} />
    </Hydrate>
  );
};
  // page.tsx
  <ErrorBoundary FallbackComponent={NoSearchContents}>
    <HydratedCarList params={params} />
  </ErrorBoundary>

여기서도 보셨듯이 fetchInfiniteQuery를 사용하시면 무한스크롤이나 페이지네이션에 이용하는 useInfiniteQuery에 대해서 ssr처리를 할 수 있습니다. (prefetchInfiniteQuery도 있습니다.)

profile
딩구르르

1개의 댓글

comment-user-thumbnail
2023년 10월 24일

이제는 기능구현 글은 안쓰시나요 ㅜ

답글 달기