TanStackQuery 공식 홈페이지 따라하기

TanStackQuery (11) - 페이지별, 무한 스크롤 쿼리 적용

vitamin3000 2025. 1. 30. 21:20

 

이번 포스트에서는 지난 포스트에서 학습한 페이지별, 무한 스크롤을 실제로 적용해보고자 한다.

 

QueryClientProvider로 최상위 컴포넌트를 감싸야 한다.

왜? -> 이것을 통해 React Query의 전역 상태를 관리하기 때문

import React from 'react';
import ReactDOM from 'react-dom/client';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; 
import App from './App';

const queryClient = new QueryClient();

ReactDOM.createRoot(document.getElementById('root')).render(
  <QueryClientProvider client={queryClient}>
    <App />
  </QueryClientProvider>
);

 

 

페이지별 쿼리

 

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

const fetchPosts = async (page = 1) => {
  const response = await fetch(`https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=30`);
  return response.json();
};

const App = () => {
  const [page, setPage] = useState(1);
  const { data: posts, isLoading } = useQuery({
    queryKey: ['posts', page],
    queryFn: () => fetchPosts(page),
  });

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

  return (
    <>
      <h1>Posts (Page {page})</h1>
      <ul>
        {posts.map(post => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
      <button onClick={() => setPage(currentPage => Math.max(currentPage - 1, 1))}>Previous Page</button>
      <button onClick={() => setPage(currentPage => currentPage + 1)}>Next Page</button>
    </>
  );
};

export default App;

 

버튼을 눌러 setPage함수가 호출되면 React는 App 컴포넌트를 다시 랜더링한다.

따라서 useQUery 훅이 다시 실행되고 page가 변경되어 그 값의 API를 호출하는 것이다.

 

무한 스크롤은 다음의 특징을 갖는다.

  • 스크롤이 특정 위치에 도달했을 때 다음 페이지의 데이터를 요청한다
  • 데이터를 표시하고 스크롤 이벤트를 감지하여 데이터를 추가로 가져온다

위 코드와 달라진 점은..

const { data, fetchNextPage, hasNextpage, isFetching } = useInfiniteQuery({
	queryKey: ['posts'],
    queryFn: fetchPosts,
    getNextPageParam: (lastPage, pages) => {
    	// 다음 페이지가 있는지 확인
        return lastPage.length ? pages.length + 1 : undefined;
    }
    getPreviousPageParam: (firstPage, pages) => {
    	return pages.length > 1 ? pages.length -1 : undefined;
    }
 });