ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 냅다 시작하는 리액트 쿼리 (SSR편)
    React.js & Next.js 2022. 12. 31. 21:05

    $ npx create-next-app test --typescript
    $ yarn add @tanstack/react-query

    _app.tsx

    import React from 'react';
    import type { AppProps } from 'next/app';
    import { Hydrate, QueryClient, QueryClientProvider } from '@tanstack/react-query';
    
    function MyApp({ Component, pageProps }: AppProps<any>) {
      const [queryClient] = React.useState(() => new QueryClient());
    
      return (
        <QueryClientProvider client={queryClient}>
          <Hydrate state={pageProps.dehydratedState}>
            <Component {...pageProps} />
          </Hydrate>
        </QueryClientProvider>
      );
    }
    
    export default MyApp;

    hydration에 대해 궁금하다면 useEffect를 통해 로그를 찍어볼 수 있습니다

    import React, { useEffect } from 'react';
    import type { AppProps } from 'next/app';
    import { Hydrate, QueryClient, QueryClientProvider } from '@tanstack/react-query';
    import { createContext } from 'react';
    
    function MyApp({ Component, pageProps }: AppProps<any>) {
      const [queryClient] = React.useState(() => new QueryClient());
      const MyContext = createContext('default value');
    
      useEffect(() => {
        console.log('- pageProps.dehydratedState:', pageProps.dehydratedState);
      }, [pageProps.dehydratedState]);
    
      return (
        <MyContext.Provider value="Hello World">
          <QueryClientProvider client={queryClient}>
            <Hydrate state={pageProps.dehydratedState}>
              <Component {...pageProps} />
            </Hydrate>
          </QueryClientProvider>
        </MyContext.Provider>
      );
    }
    
    export default MyApp;

    pages/avengers

    fetchMovies

    const fetchMovies = async (name: string) => {
      try {
        const response = await fetch(
          `https://api.themoviedb.org/3/search/movie?api_key=쿼리키&language=en-US&query=${name}`
        );
    
        if (!response) throw new Error(`Could not fetch movies -${name}`);
    
        return response.json();
      } catch (error) {
        console.error(error);
        return [];
      }
    };

    hook 또는 query 폴더로 빼서 관리해도 되지만, 편의를 위해 같이 넣어두었습니다

    getStaticProps

    서버사이드 렌더링을 지원하기 위해 getStaticProps 메서드를 사용했습니다. getStaticProps 메서드는 빌드시 서버의 요청으로 만들어진 데이터가 고정되어 넘어오는 특징이 있습니다.

    export async function getStaticProps() {
      const queryClient = new QueryClient();
    
      await queryClient.prefetchQuery(['avengers'], () => fetchMovies('avengers'));
    
      return { props: { dehydratedState: dehydrate(queryClient) } };
    }

    whole code

    import { dehydrate, QueryClient, useQuery } from '@tanstack/react-query';
    import React from 'react';
    import { REACT_APP_API_KEY } from '~/config';
    
    const fetchMovies = async (name: string) => {
      try {
        const response = await fetch(
          `https://api.themoviedb.org/3/search/movie?api_key=${REACT_APP_API_KEY}&language=en-US&query=${name}`
        );
    
        if (!response) throw new Error(`Could not fetch movies -${name}`);
    
        return response.json();
      } catch (error) {
        console.error(error);
        return [];
      }
    };
    
    const Avengers = () => {
      const { data, status } = useQuery(['avengers'], () => fetchMovies('avengers'));
    
      if (status === 'loading') return <div>Loading...</div>;
      if (status === 'error') return <div>Error Occured!</div>;
      if (status === 'success' && !data) return <div>There is no data...</div>;
    
      return (
        <>
          <div>
            <h1>Hello Avengers</h1>
    
            {data.results.map((item: any) => (
              <div key={item.id}>
                <p>
                  {item.title} - ({item.id})
                </p>
              </div>
            ))}
          </div>
        </>
      );
    };
    
    export default Avengers;
    
    export async function getStaticProps() {
      const queryClient = new QueryClient();
    
      await queryClient.prefetchQuery(['avengers'], () => fetchMovies('avengers'));
    
      return { props: { dehydratedState: dehydrate(queryClient) } };
    }

    댓글

Designed by Tistory.