useQuery를 이용하면 아래와 같이 쉽게 paginnation을 구현할 수 있습니다.
import { useQuery } from "@tanstack/react-query";
import { useState } from "react";
// 서버에서 페이지별 데이터를 가져오는 함수
async function fetchPosts(pageNumber = 1) {
const response = await fetch(
`https://jsonplaceholder.typicode.com/posts?_page=${pageNumber}`
);
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
}
const MAX_PAGE = 10;
export default function Posts() {
const [page, setPage] = useState(1);
const { data, isLoading, isError, error } = useQuery({
queryKey: ["posts", page],
queryFn: () => fetchPosts(page),
});
if (isLoading) {
return <div>Loading...</div>;
}
if (isError) {
return <div>Error : ${error.message}</div>;
}
return (
<>
<ul style={{ display: "flex", flexDirection: "column", gap: "20px" }}>
{data.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
<div style={{display: "flex", justifyContent: "space-around"}}>
<button
onClick={() => setPage((prev) => prev - 1)}
disabled={page === 1}
>
Previous Page
</button>
<span>Current Page: {page}</span>
<button
onClick={() => setPage((prev) => prev + 1)}
disabled={page === MAX_PAGE}
>
Next Page
</button>
</div>
</>
);
}
react-query는 아래와 같은 방식으로 데이터를 미리 저장할 수 있습니다.
type | where to use | data from | added to cache |
---|---|---|---|
prefetchQuery | method to queryClient | server | yes |
setQueryData | method to queryClient | client | yes |
placeholderData | option to useQuery | client | no |
initalData | option to useQuery | client | yes |
prefetchQuery
는 queryClient의 메소드로 서버로 부터 데이터를 가져와 캐시에 데이터를 저장하는 방식입니다. 이를 활용하여 페이지 데이터를 미리 가져와 로딩 없이 페이지를 보여줄 수 있어 사용자 경험을 향상 시킬 수 있습니다.
useQueryClient
: 현재의 QueryClient 인스턴스를 반환하는 hook입니다. 이 훅을 사용하면 컴포넌트 내에서 QueryClient의 메소드를 직접 호출할 수 있습니다.
const queryClient = useQueryClient();
queryClient.prefetchQuery({
queryKey: ["posts"],
queryFn: fetchPosts
});
setQueryData
역시 queryClient의 메소드로, 클라이언트 측에서 데이터를 직접 제공하여 캐시에 저장하는 방식입니다. 이를 활용하여 optimisticUpdate(낙관적 업데이트)
를 구현할 수 있습니다.
optimisticUpdate
: ****사용자가 어떤 동작을 수행할 때, 서버 응답을 기다리지 않고 UI를 먼저 업데이트하는 방식입니다. 이 후 서버 응답에 따라 실제 데이터를 업데이트하거나, 에러 시 원래 상태로 롤백할 수 있습니다.
const queryClient = useQueryClient();
queryClient.setQueryData({
queryKey: ["posts"],
queryFn: fetchPosts
});