📌아래 내용은 react-query-tutorial을 읽고 개인 공부를 위해 정리해둔 것입니다.
it makes fetching, caching, synchronizing and updating server state in your web applications a breeze.
웹 애플리케이션에서 서버 상태 가져오기, 캐싱, 동기화 및 업데이트를 보다 쉽게 다룰 수 있도록 도와줌.
TanStack Query 공식문서
import { QueryClient } from "@tanstack/react-query";
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: Infinity,
// ...
},
},
});
QueryClient에서 모든 query 또는 mutation에 기본 옵션을 추가할 수 있으며, 종류가 상당하므로 공식 문서를 참고해 보자.
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
const queryClient = new QueryClient({ /* options */});
function App() {
return (
<QueryClientProvider client={queryClient}>
<div>블라블라</div>
</QueryClientProvider>;
);
}
$ npm i @tanstack/react-query-devtools
# or
$ pnpm add @tanstack/react-query-devtools
# or
$ yarn add @tanstack/react-query-devtools
# or
$ bun add @tanstack/react-query-devtools
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
function App() {
return (
<QueryClientProvider client={queryClient}>
{/* The rest of your application */}
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
- initialIsOpen (Boolean)
true이면 개발 도구가 기본적으로 열려 있도록 설정할 수 있다.- buttonPosition?: ("top-left" | "top-right" | "bottom-left" | "bottom-right" | "relative")
기본값: bottom-right
devtools 패널을 여닫기 위한 로고 위치
relative일 때 버튼은 devtools를 렌더링하는 위치에 배치된다.- 일반적으로 initialIsOpen, buttonPosition을 자주 사용하며 그 외에 position, client와 같은 옵션들도 존재한다.
캐싱
동일한 데이터에 대한 중복 요청을 단일 요청으로 통합
백그라운드에서 오래된 데이터 업데이트
데이터가 얼마나 오래되었는지 알 수 있다.
데이터 업데이트를 가능한 빠르게 반영
페이지네이션 및 데이터 지연 로드와 같은 성능 최적화
서버 상태의 메모리 및 가비지 수집 관리
구조 공유를 사용하여 쿼리 결과를 메모화
stale은 용어 뜻대로 썩은이라는 의미이다. 즉, 최신 상태가 아니라는 의미이다.
fresh는 뜻 그대로 신선한이라는 의미이다. 즉, 최신 상태라는 의미이다.
const {
data,
// ...
} = useQuery({
queryKey: ["super-heroes"],
queryFn: getAllSuperHero,
gcTime: 5 * 60 * 1000, // 5분
staleTime: 1 * 60 * 1000, // 1분
});
📌 staleTime: (number | Infinity)
📌 gcTime: (number | Infinity)
const result = useQuery({
queryKey, // required
queryFn, // required
// ...options ex) gcTime, staleTime, select, ...
});
result.data;
result.isLoading;
result.refetch;
// ..
useQuery는 v5부터 인자로 단 하나의 객체만 받는다. 그중에 첫 번째 인자가 queryKey, queryFn가 필수 값이다.
// 실제 예제
// 💡 queryFn의 반환 타입을 지정해주면 useQuery의 타입 추론이 원활합니다.
const getAllSuperHero = async (): Promise<AxiosResponse<Hero[]>> => {
return await axios.get("http://localhost:4000/superheroes");
};
const { data, isLoading } = useQuery({
queryKey: ["super-heroes"],
queryFn: getAllSuperHero,
});
// An individual todo
useQuery({ queryKey: ["todo", 5], ... })
// An individual todo in a "preview" format
useQuery({ queryKey: ["todo", 5, { preview: true }], ...})
// (1) queryKey는 데이터를 고유하게 식별에 더해 쿼리 함수에 아래와 같이 편리하게 전달할 수도 있다.
const getSuperHero = async ({
queryKey,
}: {
queryKey: ["super-hero", number];
}): Promise<AxiosResponse<Hero>> => {
const heroId = queryKey[1]; // ex) queryKey: ["super-hero", "3"]
return await axios.get(`http://localhost:4000/superheroes/${heroId}`);
};
const useSuperHeroData = (heroId: string) => {
return useQuery({
queryKey: ["super-hero", heroId],
queryFn: getSuperHero, // (*)
});
};
useQuery의 queryFn는 Promise를 반환하는 함수를 넣어야 한다.
// (2) 상단의 queryKey 예제와 반대로 queryFn 자체적으로 인자를 받는 형태
const getSuperHero = async (heroId: string): Promise<AxiosResponse<Hero>> => {
return await axios.get(`http://localhost:4000/superheroes/${heroId}`);
};
const useSuperHeroData = (heroId: string) => {
return useQuery({
queryKey: ["super-hero", heroId],
queryFn: () => getSuperHero(heroId), // (*)
});
};
const {
data,
error,
status,
fetchStatus,
isLoading,
isFetching,
isError,
refetch,
// ...
} = useQuery({
queryKey: ["super-heroes"],
queryFn: getAllSuperHero,
});
✔️data: 쿼리 함수가 리턴한 Promise에서 resolved된 데이터
✔️error: 쿼리 함수에 오류가 발생한 경우, 쿼리에 대한 오류 객체
✔️status: data, 쿼리 결과값에 대한 상태를 표현하는 status는 문자열 형태로 3가지의 값이 존재한다.
📌 pending: 쿼리 데이터가 없고, 쿼리 시도가 아직 완료되지 않은 상태.
{ enabled: false } 상태로 쿼리가 호출되면 이 상태로 시작된다.
📌error: 에러 발생했을 때 상태
📌success: 쿼리 함수가 오류 없이 요청 성공하고 데이터를 표시할 준비가 된 상태.
✔️fetchStatus: queryFn에 대한 정보를 나타냄
📌fetching: 쿼리가 현재 실행 중인 상태
📌paused: 쿼리를 요청했지만, 잠시 중단된 상태 (network mode와 연관)
📌idle: 쿼리가 현재 아무 작업도 수행하지 않는 상태
✔️isLoading: 캐싱 된 데이터가 없을 때 즉, 처음 실행된 쿼리일 때 로딩 여부에 따라 true/false로 반환된다.
이는 캐싱 된 데이터가 있다면 로딩 여부에 상관없이 false를 반환한다.
isFetching && isPending 와 동일하다.
✔️isFetching: 캐싱 된 데이터가 있더라도 쿼리가 실행되면 로딩 여부에 따라 true/false로 반환된다.
✔️isSuccess: 쿼리 요청이 성공하면 true
✔️isError: 쿼리 요청 중에 에러가 발생한 경우 true
✔️refetch: 쿼리를 수동으로 다시 가져오는 함수.
그 외 반환 데이터들을 자세히 알고 싶으면 useQuery 공식 문서 참고
참고자료
react-query