애드블럭 종료 후 보실 수 있습니다.

ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • NextJS에서 react-query SSR 데이터 사용하기
    Next.js 2022. 6. 7. 15:18
    728x90

    react-query는 개인적으로 요즘 가장 핫한 라이브러리라고 생각한다.

    redux의 thunkAPI 등을 많이 사용했던 이전의 방식에서 react-query를 통해 get과 post방식의 query를 손쉽게 사용할 수 있으면서 데이터를 손쉽게 cache 할 수 있다는 점에서 무척이나 매력적인 라이브러리라고 할 수 있다.

     

    nextJS는 요즘에는 react개발자라면 모두 알 정도로 유명한 프레임워크이다.

    그리고 nextJS를 유명하게 만든 가장 큰 요소 중 하나는 SSR이라고 생각하는데, 아쉽게도 react-query의 hook의 경우 SSR이 아닌 CSR방식으로 데이터를 가지고 온다.

     

    이제 본격적으로 react-query의 데이터를 SSR로 사용할 수 있는 2가지 방법에 대해 설명하겠다.

     

    1. InitialData

    가장 먼저 초기에 생각했고, 지금도 많이 사용하고 있는 방법인 initialData를 사용하는 방법이다.

    이 방법의 경우 무척 직관적인 방법으로 작업하는 프로젝트에서 SSR이 적은 경우 자주 사용하고 있다.

    react-query의 기본값으로 SSR의 데이터를 넣어주는 것으로 데이터를 사용하는 간단한 방법이다.

    // apis.ts
    ...
    export const getFeeds = () => axios.get('https://api.test.com/feeds');
    ...
    
    // pages/feed-list.tsx
    
    const Test = (props) => {
      const { data } = useQuery('feeds', getFeeds, { initialData: props.feeds });
      ...
    }
    
    export async function getServerSideProps() {
      const feeds = await getFeeds();
      return { props: { feeds } };
    }

     

    2. Hydration

    본격적으로 SSR이 중요하고 다양한 곳에서 사용되는 프로젝트의 경우 많이 사용하는 방법으로 한 번의 설정 뒤로는 간편하게 SSR을 사용할 수 있다는 장점이 있다.

    redux를 사용했던 사람들이라면 이 방법이 더욱 익숙할 수도 있을 것 같다.

    // pages/_app.tsx
    
    function MyApp({ Component, pageProps }) {
      const [client] = useState(() => new QueryClient());
      
      return (
        <QueryClientProvider client={client}>
           <Hydrate state={pageProps.dehydratedState}>
             <Component {...pageProps} />
           </Hydrate>
         </QueryClientProvider>
      );
    };
    
    // apis.ts
    
    export const getFeeds = () => axios.get('https://api.test.com/feeds');
    
    // pages/feed-list.tsx
    
    const Test = (props) => {
      const { data } = useQuery('feeds', getFeeds);
      ...
    }
    
    export async function getServerSideProps() {
      const queryClient = new QueryClient();
      await queryClient.prefetchQuery('feeds', getFeeds);
      
      return {
         props: {
           dehydratedState: dehydrate(queryClient),
         },
       }
     }

    _app.tsx에 SSR 설정을 한 번 해두면 다른 모든 페이지에서 위와 같은 방법으로 사용할 수 있다.

     

    PS. Hydration에서 serializing error 해결하기

    Error serializing `.dehydratedState.queries[0].queryKey[1]` returned from `getServerSideProps` in "/feed-list". Reason: `undefined` cannot be serialized as JSON. Please use `null` or omit this value.

    두 번째 방법을 사용할 경우 가끔 위와 같은 에러가 생기는 경우가 많다.

    이 에러가 생기는 이유는 dehydrate(queryClient)의 값 중에 undefined인 값이 있어서 발생하는 에러로 생각보다 간단하게 해결 가능하다.

    ...
    dehydratedState: JSON.parse(JSON.stringify(dehydrate(queryClient))),
    ...

    위와 같이 코드를 수정해 주면 undefined였던 요소들이 모두 null값으로 변경되어 에러가 해결된다.

     

    댓글

Designed by Tistory.