Pre-fetching

김동현·2023년 2월 11일
0

React Query

목록 보기
3/5
post-thumbnail

Pre-fetching

React Query를 통해 서버 데이터를 pre-fetching할 수 있습니다. 이는 필요한 서버 데이터를 미리 fetching하고 캐싱하기때문에 서버 데이터를 요청하고 응답받는 시간을 줄일 수 있습니다.

pre-fetching한 쿼리 상태는 기본적으로 "stale 상태"를 갖고 있습니다. 해당 설정은 변경할 수 있습니다. 즉, pre-fetching된 데이터를 사용하고자 할 때 stale 상태이므로 re-fetching하게 됩니다. 이때 re-fetching하는 동안 기존 캐싱되어 있는 데이터를 사용하고 re-fetching이 완료된 이후 새롭게 re-fetching한 데이터로 교체하게 됩니다.

pre-fetching을 위한 메서드는 QueryClient로 생성한 queryClient 객체가 제공합니다.

import { useQueryClient } '@tanstack/react-query'

function Component () {
  const queryClient = useQueryClient()
  
  // pre-fethcing,,,
  queryClient.prefetchQuery(['key', ...deps], callbackFn, Options)
}

export default Component

queryClient의 prefetchQuery 메서드를 통해 pre-fetching할 수 있으며 이때 전달되는 인수는 useQuery 훅의 인수와 동일합니다.

isLoading vs isFetching

isLoading의 경우에는 캐싱된 데이터가 없고 데이터를 fetching 중인 경우 true 값을 갖습니다. 즉, 초기 데이터를 fetching 하거나 cacheTime이 만료되어 fetching하는 경우에만 isLoading 값이 true입니다.

isFetching의 경우에는 fetching 중인 경우라면 언제나 true 값을 갖습니다.

만약 pre-fetching하여 데이터를 캐싱해둔 상태라면 isLoadingfalse 값을 갖지만 isFetching의 경우에는 true 값을 갖습니다. 이는 pre-fetching된 데이터의 경우 상태가 stale이므로 re-fetching하기 때문에 isFetching의 경우 true 값을 갖게 되고, isLoading의 경우에는 데이터가 캐싱되어 있기 때문에 false 값을 갖게 됩니다.

useIsFetching

useIsFetching 훅은 fethcing 중인 쿼리의 갯수를 정수로 반환하는 훅입니다. 즉, useIsFetcing 훅의 반환값이 0 이상인 경우에는 현재 fetching 중인 쿼리가 존재한다는 것을 의미합니다.

Hydrate & dehydrate

NextJS에서 SSR 기능을 사용할 때 서버에서 query를 pre-fetching하여 dehydrate하고, 클라이언트에서 이를 rehydrate할 수 있습니다.

클라이언트에서는 pre-fetch된 서버 데이터를 포함한 HTML 문서를 즉시 렌더링할 수 있으며, 해당 쿼리 정보를 포함한 queryClient까지 전달받아 사용할 수 있습니다.

// pages/_app.tsx
import { useState } from 'react'
import {
  Hydrate,
  QueryClient,
  QueryClientProvider,
} from '@tanstack/react-query'

export default function App({ Component, pageProps }) {
  const [queryClient] = useState(() => new QueryClient())

  return (
    <QueryClientProvider client={queryClient}>
      <Hydrate state={pageProps.dehydratedState}>
        <Component {...pageProps} />
      </Hydrate>
    </QueryClientProvider>
  )
}
// pages/index.tsx
import {
  NextPage,
  QueryClient,
  dehydrate
} from '@tanstack/react-query'

const PageComponent: NextPage = () => {
  //,,,
}

export const getServerSideProps = () => {
  const queryClient = new QueryClient()
  
  await queryClient.prefetchQuery(['key'], callbackFn)
  
  return {
    props: {
      dehydratedState: dehydrate(queryClient)
    }
  }
}
  1. Query Client를 _app.tsx에서 생성해야 하며, 이를 state로서 관리해야 합니다. 이는 서버에서의 queryClient와 클라이언트에서의 queryClient 일치를 위해서이며, state로서 관리한다면 각 페이지마다 독립된 별도의 queryClient를 갖고 동작하게 됩니다.

독립된 별도의 queryClient로 관리하게 된다면, 각 페이지나 컴포넌트마다 서로 영향을 주지 않으면서 데이터를 처리할 수 있게 되며, 데이터 요구사항이 격리되어 충돌을 방지할 수 있습니다.

  1. <Hydrate> 컴포넌트의 경우 getServerSideProps에서 생성된 queryClient(pageProps.dehydratedState)를 전달받아 이를 state에 작성하면 클라이언트측에 전달되고, 클라이언트측에서는 이를 사용합니다. 만약 dehydrate된 queryClient가 없다면 <QueryClientProvider>client에 작성된 queryClient를 사용하게 됩니다.

  2. 페이지 컴포넌트에서는 getServerSideProps 내에서 queryClient를 생성하고, pre-fetch한 뒤 반환값의 props 객체 내 dehydratedState 프로퍼티에서 dehydate 함수에 queryClient를 전달한 호출문을 작성합니다.

profile
Frontend Dev

0개의 댓글