[리액트 쿼리] Tanstack-Query 알아보기

winter100·2024년 2월 7일

Tanstack-Query

목록 보기
1/2

tanstack-query

1. 리액트 쿼리(Tanstack-Query) 간단 사용법

1.1 Provider와 client 설정하기

  • 먼저 Provider와 cleint 설정을 해주어야 사용할 수 있다.
'리액트에서 사용시'

import "./App.css";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import QueryPage from "./_components/page/queryPage";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";

function App() {
  const queryClient = new QueryClient();

  return (
    <QueryClientProvider client={queryClient}>
      <QueryPage />
      <ReactQueryDevtools initialIsOpen={true} />
    </QueryClientProvider>
  );
}

export default App;
  • QueryClient, QueryClientProvider를 import하고 설정해준다
  • ReactQueryDevtools는 라이브러리를 시각화 하는데 도움을 준다.

1.2 Tanstack-Query 사용하기

  • 서버와 통신이 필요한 곳에서 사용하면 된다.
'json플레이스 홀더를 사용했다.'

import { useQuery } from "@tanstack/react-query";
import { useState } from "react";

interface PostType {
  title: string;
}

export default function QueryPage() {

  async function getData() {
    const response = await fetch(
      `https://jsonplaceholder.typicode.com/posts?_page=1`
    );
    return response.json();
  }

  const { data, isLoading } = useQuery<PostType[]>({  
     // 배열로 쿼리 키를 설정
    queryKey: ["posts"], 
    
     // http 요청할 메서드 작업
    queryFn: getData(), 
  });

    // http요청이 완료 될때까지 로딩을 띄워줌
  if (isLoading) return <div>Loading...</div>; 

  return (
    <div>
      {data?.map((item, index) => (
        <li key={index}>{item.title}</li>
      ))}
    </div>
  );
}
  • 이렇게 설정하면 해당 페이지가 열릴때 Loading..이라는 글자가 표시되고 http통신이 완료되면 title이 표시된다.
  • useQuery에는 다양한 옵션이 있으니 공식문서 에서 확인 하자

1.3 페이지네이션 설정하기

import { useQuery } from "@tanstack/react-query";
import { useState } from "react";

interface PostType {
  title: string;
}

export default function QueryPage() {
  const [currentPage, setCurrentPage] = useState(1);

  async function getData(page: number) {
    const response = await fetch(
      `https://jsonplaceholder.typicode.com/posts?_page=${page}`
    );

    return response.json();
  }

  const { data, isLoading } = useQuery<PostType[]>({
    queryKey: ["posts", currentPage],
    queryFn: () => getData(currentPage),
  });

  if (isLoading) return <div>Loading...</div>;

  return (
    <div>
      {data?.map((item, index) => (
        <li key={index}>{item.title}</li>
      ))}
      <button
        disabled={currentPage <= 1}
        onClick={() => setCurrentPage((pre) => pre - 1)}
      >
        이번 페이지
      </button>
      <button
        disabled={currentPage >= 10}
        onClick={() => setCurrentPage((pre) => pre + 1)}
      >
        다음 페이지
      </button>
    </div>
  );
}
  • queryKey를 각 페이지 마다 저장할 수 있게 currentPage 를 주고
  • queryFn도 익명함수로 currentPage를 참조 할 수 있게 해준다
  • 새로운 페이지를 볼때마다 해당 쿼리키를 갖는 해당 페이지가 렌더링 된다.
  • 또한 새로운 페이지가 렌더링 될때마다 Loading...글자가 뜨는데 UX적으로 좋지않다.
  • 이것을 해결하기 위해 preFetching을 이용 할 수 있다.
    Prefetching은 데이터가 실제로 필요하기 전에 사전에 데이터를 가져오고 캐시에 저장하는 프로세스

1.4 PreFetching 이용해보기

  • 새로운 페이지를 렌더링 할때마다 Loading... 이라는 글자가 뜨는 것을 해결하기 위해 사용 할 수 있다.
  • 사전에(미리) 다음 데이터를 받아오는 것을 뜻한다.
  • prefetching은 미리 데이터를 받아와 캐시에 저장해 둔다.
  • 미리 받아온 데이터는 stale 상태이다.
  • 미리 받아돈 데이터를 보여주면서 새로운 데이터를 받아와서 보여주는 방식이다.
// useQueryClient를 추가하기
import { useQuery, useQueryClient } from "@tanstack/react-query"; 
import { useEffect, useState } from "react";

interface PostType {
  title: string;
}

export default function QueryPage() {
  const [currentPage, setCurrentPage] = useState(1);

  async function getData(page: number) {
    const response = await fetch(
      `https://jsonplaceholder.typicode.com/posts?_page=${page}`
    );

    return response.json();
  }
---------------------------------
  // 추가된 부분
  const queryClient = useQueryClient();

  useEffect(() => {
    if (currentPage < 10) {
      const nextPage = currentPage + 1;
      queryClient.prefetchQuery({
        queryKey: ["posts", nextPage],
        queryFn: () => getData(nextPage),
      });
    }
  }, [queryClient, currentPage]);
---------------------------------

  const { data, isLoading } = useQuery<PostType[]>({
    queryKey: ["posts", currentPage],
    queryFn: () => getData(currentPage),
  });

  if (isLoading) return <div>Loading...</div>;

  return (
    <div>
      {data?.map((item, index) => (
        <li key={index}>{item.title}</li>
      ))}
      <button
        disabled={currentPage <= 1}
        onClick={() => setCurrentPage((pre) => pre - 1)}
      >
        이번 페이지
      </button>
      <button
        disabled={currentPage >= 10}
        onClick={() => setCurrentPage((pre) => pre + 1)}
      >
        다음 페이지
      </button>
    </div>
  );
}
  • queryClient와 useEffect를 이용해 prefetching을 구현했다.
  • 1번 페이지가 렌더링되면 2번페이지를 미리 받아와 캐시해둔다.
  • 다음페이지들도 마찬가지이다.

0개의 댓글