
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"],
queryFn: getData(),
});
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 상태이다.
- 미리 받아돈 데이터를 보여주면서 새로운 데이터를 받아와서 보여주는 방식이다.
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번페이지를 미리 받아와 캐시해둔다.
- 다음페이지들도 마찬가지이다.