๋ชฉ์ฐจ
npm i react-query@^3
improt { QueryClientProvider, QueryClient } from 'react-query';
improt { ReactQueryDevtools } from 'react-query/devtools';
stale time
: ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ๋ ์ต๋ ๋์ด, ๊ธฐ๋ณธ๊ฐ 0cache time
์ ํน์ ์ฟผ๋ฆฌ์ ๋ํ useQuery๊ฐ ํ์ฑํ๋ ํ ๊ฒฝ๊ณผํ ์๊ฐ, ํ์ด์ง์ ํ์๋๋ ์ปดํฌ๋ํธ๊ฐ ํน์ ์ฟผ๋ฆฌ์ ๋ํด useQuery๋ฅผ ์ฌ์ฉํ ์๊ฐ, ๋ฐ์ดํฐ๊ฐ ๋นํ์ฑํ ๋ ์ดํ ๋จ์ ์๋ ์๊ฐconst [currentPage, setCurrentPage] = useState(1); // ํ์ฌ ํ์ด์ง
// data์ ๋ค์ ํ์ด์ง ์ ๋ฌด์ ๋ํ ํ๋กํผํฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ค๋ฉด ๋ฒํผ์ ๋น.ํ์ฑํํ ์ง ํ๋จํ๋ ์งํ๋ก ์ฌ์ฉํ๋ค
const { data, isLoading, isError, error } = useQuery(
["posts", currentPage],
() => fetchPosts(currentPage),
{
staleTime: 2000,
keepPreviousData: true, // ์ด์ ํ์ด์ง๋ก ๋์๊ฐ์ ๋ ์บ์์ ํด๋น ๋ฐ์ดํฐ๊ฐ ์๋๋ก ํด์ค๋ค
}
);
...
return (
...
<div className="pages">
<button
disabled={currentPage <= 1}
onClick={() => {
setCurrentPage((prevValue) => prevValue - 1);
}}
>
Previous page
</button>
<span>Page {currentPage}</span>
<button
disabled={currentPage >= maxPostPage}
onClick={() => {
setCurrentPage((prevValue) => prevValue + 1);
}}
>
Next page
</button>
</div>
);
stale(๋ง๋ฃ)
์ํ์ด๋ค!!ํญ๊ณผ ๊ฐ์ด ํต๊ณ์ ์ผ๋ก ํน์ ํญ์ ๋๋ฅผ ํ๋ฅ ์ด ๋์ ๊ฒฝ์ฐ
ํด๋น ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋ฆฌ ๊ฐ์ ธ์ค๋ ๊ฒ์ด ์ข์!!import { useQuery, useQueryClient } from "react-query";
const maxPostPage = 10;
const queryClient = useQueryClient();
useEffect(() => {
if (currentPage < maxPostPage) {
// ํ์ด์ง๊ฐ 11์ผ ๋ fetchํ์ง ์๊ฒ
const nextPage = currentPage + 1;
queryClient.prefetchQuery(["posts", currentPage], () =>
fetchPosts(nextPage)
);
}
}, [currentPage, queryClient]);
๐ prefetchQuery(["posts", currentPage], ...)
๐ฅ currentPage -> ์์กด์ฑ ๋ฐฐ์ด์ ์ถ๊ฐํ๋ ์ด์
โ
useQuery(, , {keepPreviousData: true})
keepPreviousData: true,
// ์ด์ ํ์ด์ง๋ก ๋์๊ฐ์ ๋ ์บ์์ ํด๋น ๋ฐ์ดํฐ๊ฐ ์๋๋ก ํด์ค๋ค. ์ฟผ๋ฆฌ ํค๊ฐ ๋ณ๊ฒฝ๋ ๋๊น์ง ์ด์ ์ ๋ชจ๋ ๋ฐ์ดํฐ๊ฐ ๊ทธ๋๋ก ์ ์ง๋๋ค. ํ์นํ๋ ๋์ ์ด์ ๋ฐ์ดํฐ๋ฅผ ์๋ฆฌํ์์๋ก ์ฌ์ฉํ๋ ๊ฒ
โญ๏ธ isLoading vs isFetching
export function Posts() {
const [currentPage, setCurrentPage] = useState(1); // ํ์ฌ ํ์ด์ง
const [selectedPost, setSelectedPost] = useState(null);
const queryClient = useQueryClient();
useEffect(() => {
if (currentPage < maxPostPage) {
// ํ์ด์ง๊ฐ 11์ผ ๋ fetchํ์ง ์๊ฒ
const nextPage = currentPage + 1;
queryClient.prefetchQuery(["posts", currentPage], () =>
fetchPosts(nextPage)
);
}
}, [currentPage, queryClient]);
// data์ ๋ค์ ํ์ด์ง ์ ๋ฌด์ ๋ํ ํ๋กํผํฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ค๋ฉด ๋ฒํผ์ ๋น.ํ์ฑํํ ์ง ํ๋จํ๋ ์งํ๋ก ์ฌ์ฉํ๋ค
const { data, isLoading, isError, error } = useQuery(
["posts", currentPage],
() => fetchPosts(currentPage),
{
staleTime: 2000,
keepPreviousData: true, // ์ด์ ํ์ด์ง๋ก ๋์๊ฐ์ ๋ ์บ์์ ํด๋น ๋ฐ์ดํฐ๊ฐ ์๋๋ก ํด์ค๋ค
}
); // key / ๋น๋๊ธฐ ํจ์
// fetchPosts๊ฐ ๋น๋๊ธฐ์ด๊ธฐ ๋๋ฌธ์ ์๋ฃ๋๊ธฐ ์ ๊น์ง๋ query์ ์ ์ฅ๋์ง ์์
if (isLoading) return <div>Loading....</div>;
if (isfetching) return <div>Fetching in pregress</div>;
if (isError) return <div>{error.toString()}</div>;
return (...);
}
import { useQuery, useMutation } from "react-query";
async function deletePost(postId) {
const response = await fetch(
`https://jsonplaceholder.typicode.com/postId/${postId}`,
{ method: "DELETE" }
);
return response.json();
}
...
// ์ธ์๋ก ์ฝ๋ฐฑํจ์ ์ง์
const deleteMutation = useMutation((postId) => deletePost(postId));
...
return (
// useMutation์ด ๋ฐํํ๋ ํจ์์ mutate๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค!
// mutate๋ฉ์๋์ ์ธ์๋ก post.id๋ฅผ ์ ๋ฌํ์ฌ, post.id๊ฐ ์ฝ๋ฐฑํจ์์ ์ธ์๋ก ๋ค์ด๊ฐ fetchํจ์์ ์ ๋ฌํ๋ค.
<button onClick={() => deleteMutation.mutate(post.id)}>Delete</button>
// isError, isLoading, isSuccess ํ๋ฌํผํฐ๋ฅผ ์ฌ์ฉํ๋ค.
{deleteMutation.isError && (
<p style={{ color: "red" }}>Error deleting the post</p>
)}
{deleteMutation.isLoading && (
<p style={{ color: "purple" }}>Deleting the post</p>
)}
{deleteMutation.isSuccess && (
<p style={{ color: "green" }}>Post has (not) been deleted</p>
)}
);
async function updatePost(postId) {
const response = await fetch(
`https://jsonplaceholder.typicode.com/postId/${postId}`,
{ method: "PATCH", data: { title: "REACT QUERY FOREVER!!!!" } }
);
return response.json();
}
...
const updateMutation = useMutation((postId) => updatePost(postId));
return (
<button onClick={() => updateMutation.mutate(post.id)}>Update title</button>
{updateMutation.isError && (
<p style={{ color: "red" }}>Error updating the post</p>
)}
{updateMutation.isLoading && (
<p style={{ color: "purple" }}>Updating the post</p>
)}
{updateMutation.isSuccess && (
<p style={{ color: "green" }}>Post has (not) been updated</p>
)}
);