react-query๋ react application์์ ์๋ฒ ์ํ ํ์นญ, ์บ์ฑ, ๋๊ธฐํ ๋ฐ ์ ๋ฐ์ดํธ๋ฅผ ๋ณด๋ค ์ฝ๊ฒ ๋ค๋ฃฐ ์ ์๋๋ก ๋์์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค.
QueryClient๋ ์ ํ๋ฆฌ์ผ์ด์ ๋ด ์ ์ผํด์ผํ๋ฉฐ QueryClient๋ฅผ ํตํด ์บ์์ ์ํธ์์ฉ์ ํ ์ ์์ผ๋ฉฐ ๋ชจ๋ query์ mutation์ ๊ธฐ๋ณธ ์ต์ ์ ์ค์ ํ ์ ์์ต๋๋ค.
QueryClient๋ ์์ฑ์๋ก new ์ฐ์ฐ์์ ํจ๊ป ํธ์ถํด์ผ ํ๋ฉฐ, ํธ์ถํ ๋ defaultOptions ํ๋กํผํฐ์ ์ฟผ๋ฆฌ์ ๋ํ ์ต์ ์ ์ค์ ํ ๊ฐ์ฒด๋ฅผ ์ธ์๋ก ์ ๋ฌํ ์ ์์ต๋๋ค.
QueryClientProvider ์ปดํฌ๋ํธ๋ฅผ ์ต์๋จ์ ์์น์ํค๊ณ client props์ ์์ฑํ QueryClient ์ธ์คํด์ค๋ฅผ ์ ๋ฌํด์ค๋๋ค.
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
export default function App() {
const queryClient = new QueryClient({
defaultOptions: {
// ๋ชจ๋ ์ฟผ๋ฆฌ์ ๊ณตํต์ ์ผ๋ก ์ ์ฉ๋๋ ์ต์
์ ์ค์ ํ ์ ์์ต๋๋ค.
queries: {
// ์ฟผ๋ฆฌ๋ฅผ ์ฒ์ ์คํํ ๋ ์ฌ์ฉ๋๋ ์ด๊ธฐ ๋ฐ์ดํฐ์
๋๋ค.
initialData: undefined,
// ์ฟผ๋ฆฌ๊ฐ ๋ฐ์ดํฐ๋ฅผ ํ์นญํ๋ ๋์ ์ปดํฌ๋ํธ์ ์ ๊ณต๋ ์์ ๋ฐ์ดํฐ๋ฅผ ์ค์ ํฉ๋๋ค.
placeholderData: undefined,
// ์ด๊ธฐ ๋ฐ์ดํฐ๊ฐ ๋ง์ง๋ง์ผ๋ก ์
๋ฐ์ดํธ๋ ์๊ฐ์ ํ์์คํฌํ(๋ฐ๋ฆฌ์ด)๋ก ์ค์ ํฉ๋๋ค.
initialDataUpdatedAt: undefined,
// ์ฟผ๋ฆฌ์ ๊ด๋ จ๋ ์ถ๊ฐ ์ ๋ณด๋ฅผ ์ ๋ฌํ ์ ์์ต๋๋ค.
// meta๋ ์ฟผ๋ฆฌ์ ์ ๊ทผํ ์ ์๋ ๋ชจ๋ ๊ณณ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
meta: undefined,
// ์ฟผ๋ฆฌ์ ์์ฒญ ๋ฐฉ์์ ์ค์ ํ๋ ์ต์
์
๋๋ค.
// online: ์์ฒญ์ ์ฐ์ ์ ์ผ๋ก ์ํํ๊ณ ์บ์๋ ๋ฐ์ดํฐ๋ฅผ ํ์์์ ์ฌ์ฉํฉ๋๋ค.
// offlineFirst: ์บ์๋ ๋ฐ์ดํฐ๋ฅผ ์ฐ์ ์ ์ผ๋ก ์ฌ์ฉํ์ฌ ์์ฒญ ์ํ์ ์ต์ํํฉ๋๋ค.
// always: ์บ์๋ ๋ฐ์ดํฐ๊ฐ ์๋๋ผ๋ ํญ์ ์์ฒญ์ ์ํํฉ๋๋ค.
networkMode: 'online',
// ์ปดํฌ๋ํธ์ ๋ฆฌ๋ ๋๋ง์ ์ ์ดํ ์ ์์ต๋๋ค.
notifyOnChangeProps: 'all',
// ์ฟผ๋ฆฌ ํ์ฑํ ์ฌ๋ถ๋ฅผ ์ค์ ํฉ๋๋ค.
enabled: true,
// ์ฟผ๋ฆฌ ๋ฐ์ดํฐ๊ฐ fresh ์ํ์์ stale ์ํ๋ก ๋ณ๊ฒฝ๋๊ธฐ๊น์ง์ ์๊ฐ์ ์ค์ ํฉ๋๋ค.
staleTime: 0,
// inactive ์ํ์ธ ์ฟผ๋ฆฌ ๋ฐ์ดํฐ๊ฐ ๊ฐ๋น์ง ์ปฌ๋ ํ
๋๊ธฐ๊น์ง์ ์๊ฐ์ ์ค์ ํฉ๋๋ค.
gcTime: 30000,
// ์ฟผ๋ฆฌ ์คํจ์ ์ฌ์๋ ํ์๋ฅผ ์ค์ ํฉ๋๋ค.
retry: 3,
// retry ์ฌ์ด์ ๋๊ธฐ ์๊ฐ์ ์ค์ ํฉ๋๋ค.
// ์ฒซ ๋ฒ์งธ ์ธ์๋ก๋ ์คํจ ํ์, ๋ ๋ฒ์ฌ ์ธ์๋ก๋ ์๋ฌ ๊ฐ์ฒด๋ฅผ ์ ๋ฌ๋ฐ์ต๋๋ค.
retryDelay: (failureCount, error) => Math.min(1000 * 2 ** failureCount, 30000),
// ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋ ๋ ์คํจํ ์ฟผ๋ฆฌ๋ฅผ ๋ค์ ์๋ํ ์ง ์ฌ๋ถ๋ฅผ ์ค์ ํฉ๋๋ค.
retryOnMount: true,
// ์ฟผ๋ฆฌ์ ๋ฐ์ดํฐ๋ฅผ ์ผ์ ํ ๊ฐ๊ฒฉ์ผ๋ก refetchingํ ์ ์๋๋ก ์ค์ ํฉ๋๋ค.
refetchInterval: false,
// ์ฟผ๋ฆฌ๊ฐ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ํ
์์๋ ์ผ์ ํ ๊ฐ๊ฒฉ์ผ๋ก refetchingํ ์ ์๋๋ก ์ค์ ํฉ๋๋ค.
refetchIntervalInBackground: false,
// ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋ ๋ ์ฟผ๋ฆฌ์ ๋ฐ์ดํฐ๋ฅผ ์๋์ผ๋ก fetchingํ ์ง ์ฌ๋ถ๋ฅผ ์ค์ ํฉ๋๋ค.
refetchOnMount: true,
// ๋คํธ์ํฌ๊ฐ ๋ค์ ์ฐ๊ฒฐ๋ ๋ ์ฟผ๋ฆฌ์ ๋ฐ์ดํฐ๋ฅผ ์๋์ผ๋ก fetchingํ ์ง ์ฌ๋ถ๋ฅผ ์ค์ ํฉ๋๋ค.
refetchOnReconnect: true,
// ๋ธ๋ผ์ฐ์ ์ ๋ค์ ํฌ์ปค์ฑ๋์์ ๋ ์ฟผ๋ฆฌ์ ๋ฐ์ดํฐ๋ฅผ ์๋์ผ๋ก fetchingํ ์ง ์ฌ๋ถ๋ฅผ ์ค์ ํฉ๋๋ค.
refetchOnWindowFocus: true,
// ์ฟผ๋ฆฌ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ณตํ ๋ ์ฌ์ฉํ๋ ์ต์
์ผ๋ก ์ฟผ๋ฆฌ ์๋ณธ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ฑฐ๋ ํํฐ๋งํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
// ์ธ์๋ก ์๋ณธ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌ๋ฐ์ผ๋ฉฐ ๋ฐํ๊ฐ์ด ์ต์ข
์ ์ผ๋ก ๋ฐํ๋๋ data์ ๋ฐ์ธ๋ฉ๋ฉ๋๋ค.
select: undefined,
// ๊ธฐ์กด ๋ฐ์ดํฐ์ ์๋ก์ด ๋ฐ์ดํฐ ๊ฐ์ ์ฐจ์ด์ ์ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ ์ต์
์
๋๋ค.
// true: ๋ณ๊ฒฝ๋ ๋ถ๋ถ๋ง ์
๋ฐ์ดํธํ๊ณ ๋๋จธ์ง ๋ฐ์ดํฐ๋ ์ฌ์ฌ์ฉํฉ๋๋ค.
// false: ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์ ์ฒด ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์๋ก ์์ฑํฉ๋๋ค.
structuralSharing: true,
// ์ฟผ๋ฆฌ์์ ๋ฐ์ํ ์๋ฌ๋ฅผ ์ปดํฌ๋ํธ ๋๋ ์์ ์ปจํ
์คํธ์๊ฒ ์ ๋ฌ๋๋๋ก ์ค์ ํ๋ ์ต์
ฅ์
๋๋ค.
throwOnError: false,
// ์ฟผ๋ฆฌ์ ๊ธฐ๋ณธ ๋์ ๋ฐฉ์์ ์ ์ํ ์ ์๋ ์ต์
์
๋๋ค.
behavior: {
// queryFn์ด ์คํ๋๊ธฐ ์ ์ ์คํ๋๋ ๋ฉ์๋์
๋๋ค.
onFetch(context) {
// useQuery์ ์ง์ ํ queryFn๊ณผ ๋์ผํ ํจ์์ด๋ฉฐ ์ฟผ๋ฆฌ ํจ์์ ์ง์ ์ ๊ทผํ๊ณ ์คํํ ์ ์์ต๋๋ค.
context.fetchFn();
// refetch ์์ฒญ์ ์ทจ์ํ ์ ์๋ ์ต์
์ด๋ฉฐ false๋ก ์ค์ ์ refetch๋ฅผ ๋ง์ ์ ์์ต๋๋ค.
context.fetchOptions?.cancelRefetch;
// ์ฟผ๋ฆฌ๊ฐ ์ด๊ธฐ ์ํ์ผ ๋ ์ฌ์ฉํ๋ ํ๋ก๋ฏธ์ค ๊ฐ์ฒด๋ฅผ ์ค์ ํ ์ ์์ต๋๋ค.
context.fetchOptions?.initialPromise;
// ํ์ด์ง๋ค์ด์
์ด๋ ๋ฌดํ ์คํฌ๋กค ์ ๋ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ๋ ๋ฐฉํฅ('forward', 'backward')์ ์ค์ ํ ์ ์์ต๋๋ค.
context.fetchOptions?.meta?.fetchMore?.direction;
// ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ๋ ์ฌ์ฉ๋ ์ต์
๋ค์ ์ค์ ํ ์ ์์ต๋๋ค.
context.options;
// useQuery์์ ์ง์ ํ queryKey ๊ฐ์ ๊ฐ๊ณ ์์ต๋๋ค.
context.queryKey;
// AbortSignal๋ฅผ ์ฌ์ฉํ์ฌ fetch ์์ฒญ์ ์ทจ์ํ ์ ์๋๋ก ๋์์ฃผ๋ AbortSignal ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ๋์ด ์์ต๋๋ค.
context.signal;
// ์ฟผ๋ฆฌ์ ํ์ฌ ์ํ ์ ๋ณด๋ฅผ ์ ๊ณตํฉ๋๋ค.
context.state;
}
}
},
// ๋ชจ๋ ๋ฎคํ
์ด์
์ ๊ณตํต์ ์ผ๋ก ์ ์ฉ๋๋ ์ต์
์ ์ค์ ํ ์ ์์ต๋๋ค.
mutations: {
scope: {
// ๋ณ๋ ฌ๋ก ์คํ๋๋ ์ฌ๋ฌ mutationFn ํจ์์ค id๋ก ์์ฑ๋ mutaitonFn๋ค์ ์ง๋ ฌ๋ก ์คํ๋๋๋ก ์ค์ ํฉ๋๋ค.
id: ''
},
// mutationFn ์ฑ๊ณต์ ์คํ๋๋ ๋ฉ์๋์
๋๋ค.
onSuccess: undefined,
// mutationFn ์คํจ์ ์คํ๋๋ ๋ฉ์๋์
๋๋ค.
onError: undefined,
// mutationFn ์ฑ๊ณต ํน์ ์คํจ์ ์คํ๋๋ ๋ฉ์๋์
๋๋ค.
onSettled: undefined
},
// SSR์ด๋ SSG ํ๊ฒฝ์์ dehydrate์ ์ฟผ๋ฆฌ ์ํ ์ฒ๋ฆฌ๋ฅผ ์ ์ดํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
dehydrate: {
// ๋ฐ์ดํฐ์ ์ง๋ ฌํ ๋ฐฉ์์ ์ ์ํ๋ ํจ์๋ฅผ ์์ฑํฉ๋๋ค.
serializeData: undefined,
// ํน์ ์ฟผ๋ฆฌ๋ฅผ ์ง๋ ฌํํ ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ ํจ์๋ฅผ ์์ฑํฉ๋๋ค.
shouldDehydrateQuery: () => true,
// ํน์ ๋ฎคํ
์ด์
์ ์ง๋ ฌํํ ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ ํจ์๋ฅผ ์์ฑํฉ๋๋ค.
shouldDehydrateMutation: () => false
},
// SSR์ด๋ SSG ํ๊ฒฝ์์ hydrate์ ์ฟผ๋ฆฌ ์ํ ์ฒ๋ฆฌ๋ฅผ ์ ์ดํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
hydrate: {
// ๋ฐ์ดํฐ์ ์ญ์ง๋ ฌํ ๋ฐฉ์์ ์ ์ํ๋ ํจ์๋ฅผ ์์ฑํฉ๋๋ค.
deserializeData: undefined,
// MutationOptions์ ์์ฑํฉ๋๋ค.
mutations: {
// ...MutationOptions
},
// QueryOptions์ ์์ฑํฉ๋๋ค.
queries: {
// ...QueryOptions
}
}
}
});
// QueryClientProvider๋ฅผ ์ต์๋จ์์ ๊ฐ์ธ์ฃผ๊ณ QueryClient ์ธ์คํด์ค๋ฅผ client props๋ก ๋ฃ์ด ์ ํ๋ฆฌ์ผ์ด์
์ ์ฐ๊ฒฐํด์ผ ํ๋ค.
return <QueryClientProvider client={queryClient}>,,,</QueryClientProvider>;
}QueryClientProvider ์ปดํฌ๋ํธ๋ Context API๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ์๋ฒ ์ปดํฌ๋ํธ์ ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก ํด๋ผ์ด์ธํธ ์ปดํฌ๋ํธ๋ก ๋ถ๋ฆฌํ์ฌ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
// ReactQueryProviders.tsx
'use client';
import { useState, PropsWithChildren } from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
export default function ReactQueryProviders({ children }: PropsWithChildren) {
const [queryClient] = useState(
() =>
new QueryClient({
defaultOptions: {
queries: {
// ํด๋ผ์ด์ธํธ์ธก์์ ์ฆ์ refetching๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด์ staleTime ๊ฐ์ 0์ผ๋ก ์ฌ์ฉ๋์ฆ ๊ฒ์ ๋ฐฉ์ง
staleTime: 60 * 1000
}
}
})
);
return (
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>>
)
}// app/layout.tsx
import { PropsWithChildren } from 'react';
import ReactQueryProviders from '@/shared/components/ReactQueryProviders';
export default function RootLayout({ children }: PropsWithChildren) {
return (
<html>
<head />
<body>
<ReactQueryProviders>{children}</ReactQueryProviders>
</body>
</html>
);
}์๋ฒ์์ prefethํ ์ฟผ๋ฆฌ๋ค์ ๊ฐ๋ queryClient๋ฅผ dehydrate์์ผฐ๋ค๊ฐ ์ดํ ํด๋ผ์ด์ธํธ์ธก์ ์ ๋ฌํ ๋๋ hydrate ์์ผ ์ ๋ฌํด์ฃผ์ด์ผ ํฉ๋๋ค.
// getDehydratedQuery.ts
import {
QueryClient,
dehydrate,
QueryState,
QueryKey
} from '@tanstack/react-query';
import { cache } from 'react';
import { isEqual } from '@/utils';
// cache ํจ์๋ฅผ ์ฌ์ฉํ์ฌ QueryClient๋ฅผ ๋งค๋ฒ ์์ฑํ์ง ์๊ณ ์บ์ฑ๋ queryClient๋ฅผ ์ฌ์ฌ์ฉ
export const getQueryClient = cache(() => new QueryClient());
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
interface QueryProps<ResponseType = unknown> {
queryKey: QueryKey;
queryFn: () => Promise<ResponseType>;
}
interface DehydratedQueryExtended<TData = unknown, TError = unknown> {
state: QueryState<TData, TError>;
}
export async function getDehydratedQuery<Q extends QueryProps>({
queryKey,
queryFn,
}: Q) {
const queryClient = getQueryClient();
// ํ์ํ ์ฟผ๋ฆฌ๋ฅผ prefetching
await queryClient.prefetchQuery({ queryKey, queryFn });
// perfetchingํ ์ฟผ๋ฆฌ๋ฅผ ๊ฐ๊ณ ์๋ queryClient๋ฅผ dehydate
// dehydate ๋ฉ์๋๋ ์ฟผ๋ฆฌ๋ค์ ์ง๋ ฌํ์ํค๊ณ ์ด๋ฅผ ์ด์ฉํ์ฌ per-rendering
const { queries } = dehydrate(queryClient);
// dehydate ํจ์๋ prefetcingํ ๋ชจ๋ ๋ฐ์ดํฐ๋ค์ ๋ฐํํ๊ธฐ ๋๋ฌธ์ ์์ฒญํ ์ฟผ๋ฆฌ๋ง์ ํํฐ๋งํ์ฌ ๋ฐํ
const [dehydratedQuery] = queries.filter((query) =>
isEqual(query.queryKey, queryKey)
);
return dehydratedQuery as DehydratedQueryExtended<
UnwrapPromise<ReturnType<Q['queryFn']>>
>;
}// app/page.tsx
import { HydrationBoundary } from 'react-query';
import { getDehydratedQuery } from '@/app/shared/utils/getDehydratedQuery';
export default async function Home({ children }: PropsWithChildren) {
const { queryKey, queryFn } = queryOptions.all();
const query = await getDehydratedQuery({ queryKey, queryFn });
return (
<main>
{/* HydrationBoundary ์ปดํฌ๋ํธ๋ ํด๋ผ์ด์ธํธ์ธก์์ dehydrated๋ ์ฟผ๋ฆฌ๋ค์ ์ญ์ง๋ ฌํ ์์ผ hydration ๊ณผ์ ์์ ์ด๊ธฐ ์ฟผ๋ฆฌ๋ค๋ก ์ฌ์ฉ */}
<HydrationBoundary state={{ queries: [query] }}>{children}</HydrationBoundary>
</main>
);
}- fresh
query์ ์ค์ ๋ staleTime์ด ์ง๋์ง ์์ ์ํ์ด๋ฉฐ, fresh ์ํ์์๋ refetchingํ์ง ์์ผ๋ฉฐ ์บ์ฑ๋ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
- fetching
queryFn์ด ์คํ์ค์ธ ์ํ์ ๋๋ค.
- stale
query์ ์ค์ ๋ staleTime์ด ์ง๋ฌ์ผ๋ฉฐ ์ด๋ refetchingํ์ฌ ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ ์บ์ฑํ๊ฒ ๋ฉ๋๋ค. ์ด๋ refetchingํ๋ ๋์์๋ ๊ธฐ์กด stale ์ํ์ ์ฟผ๋ฆฌ๋ฅด ์ฌ์ฉํ๋ฉฐ ์ดํ refething์ด ์๋ฃ๋๋ฉด ์๋ก์ด ๋ฐ์ดํฐ๋ก ๊ต์ฒดํ๊ณ ์ด๋ฅผ ์บ์ฑํ๊ฒ ๋ฉ๋๋ค.
- inactive
์ฟผ๋ฆฌ๊ฐ ์คํ๋ ์ปดํฌ๋ํธ๊ฐ unmount๋๋ ๊ฒฝ์ฐ ํด๋น ์ฟผ๋ฆฌ๋ inactive ์ํ๊ฐ ๋ฉ๋๋ค. inactive ์ํ๋ ์ฌ์ฉ๋์ง๋ ์์ง๋ง ๋ฉ๋ชจ๋ฆฌ์ ์์ง ์บ์ฑ๋์ด ์๋ ์ํ์ ๋๋ค.
- delete
inactive ์ํ์ธ ์ฟผ๋ฆฌ์ ์ค์ ๋ gcTime์ด ์ง๋ ์ํ์ด๋ฉฐ ์ด๋ ๊ฐ๋น์ง ์ปฌ๋ ํฐ์ ์ํด ๋ฉ๋ชจ๋ฆฌ์์์ ์ ๊ฑฐ๋ฉ๋๋ค.
import { useQuery } from 'react-query';
async function fetchData() {
return fetch('https://,,,', { method: 'GET' });
}
const {
data, // queryFn์ด ๋ฐํํ ๊ฐ, ์ด๊ธฐ queryFn ์คํ์ด ์๋ฃ๋๊ธฐ ์ ์๋ undefined ๋ฐํ
dataUpdatedAt, // ๋ง์ง๋ง์ผ๋ก fetchingํ ํ์์คํฌํ
error, // queryFn ์คํ ์ค ์๋ฌ ๋ฐ์ํ ๊ฒฝ์ฐ ์๋ฌ ๊ฐ์ฒด๊ฐ ๋ฐ์ธ๋ฉ
isError, // queryFn ์คํ ์ค ์๋ฌ ๋ฐ์ ์ฌ๋ถ
errorUpdateCount, // ์๋ฌ๊ฐ ๋ฐ์ฃํ๊ธฐ ๊น์ง์ queryFn ์คํ ํ์
errorUpdatedAt, // ๋ง์ง๋ง์ผ๋ก ์๋ฌ๊ฐ ๋ฐ์ํ ํ์์คํฌํ
failureCount, // ์๋ฌ๊ฐ ๋ฐ์ํ ํ์
failureReason, // ๋ง์ง๋ง์ผ๋ก ๋ฐ์ํ ์๋ฌ์ ๋ฉ์ธ์ง ํน์ ๊ฐ์ฒด
fetchStatus, // ํ์ queryFn ์คํ ์ํ ๋ฐํ(idle, fetching, pause)
isFetched, // queryFn์ด ์ฑ๊ณต์ ์ผ๋ก ์คํ๋์๋์ง ์ฌ๋ถ
isFetchedAfterMount, // ๋ง์ดํธ๋ ์ดํ queryFn์ด ์ฑ๊ณต์ ์ผ๋ก ์คํ๋์๋์ง ์ฌ๋ถ
isFetching, // queryFn์ด ํ์ฌ ์คํ์ค์ธ์ง ์ฌ๋ถ
isLoading, // queryFn์ด ์ฒซ ์คํ์ด๋ฉฐ ํ์ฌ ์คํ์ค์ธ์ง ์ฌ๋ถ
isLoadingError, // queryFn ์ฒซ ์คํ์ค ์๋ฌ ๋ฐ์ ์ฌ๋ถ
isPaused, // queryFn ์ผ์ ์ค์ง ์ฌ๋ถ
isPending, // queryFn ์คํ ๋๊ธฐ์ค ์ฌ๋ถ(isFetching๊ณผ ์ ์ฌํ์ง๋ง ๋ ํฌ๊ด์ )
isPlaceholderData, // ํ์ฌ data๊ฐ placeholder ๋ฐ์ดํฐ์ธ์ง ์ฌ๋ถ
isRefetchError, // refetching ๋์ค ์๋ฌ ๋ฐ์ ์ฌ๋ถ
isRefetching, // ํ์ฌ refetching ์ค์ธ์ง ์ฌ๋ถ
isStale, // ์บ์ฑ ์ํ๊ฐ stale์ธ์ง ์ฌ๋ถ
isSuccess, // queryFn์ด ์ฑ๊ณต์ ์ผ๋ก ์คํ๋์๋์ง ์ฌ๋ถ
refetch, // ์๋์ผ๋ก refetchingํ๋ ํจ์
status // ํ์ฌ ์ฟผ๋ฆฌ ์ํ๋ฅผ ๋ฐํ(idle, loading, error, success)
} = useQuery({
/**
* queryKey๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์บ์ฑ ๊ด๋ฆฌ๋๋ฉฐ ๋ง์ฝ queryFn ํจ์ ๋ด์์ ํน์ ๋ณ์์
* ์์กดํ๊ณ ์๋ค๋ฉด queryKey ๋ฐฐ์ด ์์๋ก ์ถ๊ฐํด์ฃผ์ด์ผ ํจ.
* **/
queryKey: ['queryKey'],
queryFn: fetchData // Promise ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ํจ์ ์์ฑ
});import { useQueries } from 'react-query';
async function fetchData1() {
return fetch('https://,,,', { method: 'GET' });
}
async function fetchData2() {
return fetch('https://,,,', { method: 'GET' });
}
/**
* useQueries ํ
์ ์ฌ๋ฌ ์ฟผ๋ฆฌ๋ค์ ๋ณ๋ ฌ๋ก ์์ฒญํ๊ณ
* ๋ชจ๋ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ ํฌํจ๋ ๋ฐฐ์ด์ ๋ฐํ
* **/
const queryResults = useQueries({
queries: [
{
queryKey: ['fetchData1'],
queryFn: fetchData1
},
{
queryKey: ['fetchData2'],
queryFn: fetchData2
}
]
});useSuspenseQuery ํ ์ Suspense์ ํจ๊ป ์ฌ์ฉํ๋ฉด ์ฟผ๋ฆฌ ์ํ(status)๊ฐ loading์ธ ๊ฒฝ์ฐ Suspense์ fallback props์ ์ค์ ํ ์ปดํฌ๋ํธ๋ฅผ ํ์ํด์ค๋๋ค.
import { useSuspenseQuery } from 'react-query';
export default function Child() {
async function fetchData() {
return fetch('https://,,,', { method: 'GET' });
}
const queryResult = useSuspenseQuery({
queryKey: ['queryKey'],
queryFn: fetchData
});
return <div>{/* ,,, */}</div>;
}import { Suspense } from 'react';
export default function Parent() {
return (
<Suspense fallback={<div>loading,,,</div>}>
<Child />
</Suspense>
);
}useInfiniteQuery ํ ์ ํน์ ์กฐ๊ฑด์์ ์ถ๊ฐ์ ์ธ ๋ฐ์ดํฐ๋ฅผ fetching ๊ธฐ๋ฅ์ ์ ๊ณตํด์ค๋๋ค. ์ด๋ฅผ ํตํด ๋ฌดํ ์คํฌ๋กค ์ด๋ ํ์ด์ง ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์์ต๋๋ค.
import { useInfiniteQuery } from '@tanstack/react-query';
const {
data: {
pages, // ๋ชจ๋ ํ์ด์ง์ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋ ๋ฐฐ์ด
pageParams // ๋ชจ๋ ํ์ด์ง์ ๋ํ pageParam ๋ฐฐ์ด
},
fetchNextPage, // ๋ค์ ํ์ด์ง์ ๋ฐ์ดํฐ๋ฅผ fetchingํ๋ ํจ์์ด๋ฉฐ, ํธ์ถ์ queryFn์ด ์คํ
fetchPreviousPage, // ์ด์ ํ์ด์ง์ ๋ฐ์ดํฐ๋ฅผ fethcingํ๋ ํจ์
hasNextPage, // ๋ค์ ํ์ด์ง ์กด์ฌ ์ฌ๋ถ๋ฅผ ๋ฐํ. ํด๋น ๊ฐ์ getNextPageParam ํจ์๊ฐ undefined์ธ ๊ฒฝ์ฐ true ๋ฐํ
hasPreviousPage, // ์ด์ ํ์ด์ง์ ์กด์ฌ ์ฌ๋ถ ๋ฐํ. getPreviousPageParam ํจ์๊ฐ undefined์ธ ๊ฒฝ์ฐ true ๋ฐํ
isFetchingNextPage, // ๋ค์ ํ์ด์ง์ ๋ฐ์ดํฐ๋ฅผ fetching ์ค์ธ์ง ์ฌ๋ถ๋ฅผ ๋ฐํ
isFetchingPreviousPage, // ์ด์ ํ์ด์ง์ ๋ฐ์ดํฐ๋ฅผ fetching ์ค์ธ์ง ์ฌ๋ถ๋ฅผ ๋ฐํ
...result
} = useInfiniteQuery({
queryKey, // ์ฟผ๋ฆฌ๋ฅผ ๊ณ ์ ํ๊ฒ ์๋ณํ๋ ํค
queryFn: ({ pageParam }) => fetchPage(pageParam), // ๋ฐ์ดํฐ๋ฅผ fetchingํ๋ ๋น๋๊ธฐ ํจ์, ์ธ์๋ก pageParam ์ ๋ฌ๋ฐ์ ์คํ
initialPageParam: 1, // ์ด๊ธฐ pageParam ๊ฐ
getNextPageParam: (lastPage, allPages, lastPageParam, allPageParams) => lastPage.nextCursor, // ๋ค์ ํ์ด์ง์ queryFn ํจ์ pageParam ๊ฐ ๋ฐํ. ์ธ์๋ก ํ์ฌ ํ์ด์ง์ ๋ฐ์ดํฐ, ์ ์ฒด ํ์ด์ง์ ๋ฐ์ดํฐ ๋ฐฐ์ด, ํ์ฌ ํ์ด์ง์ pageParam, ์ ์ฒด ํ์ด์ง์ pageParam ๋ฐฐ์ด์ ์ ๋ฌ๋ฐ์ ์คํ
getPreviousPageParam: (firstPage, allPages, firstPageParam, allPageParams) => firstPage.prevCursor // ์ด์ ํ์ด์ง์ queryFn ํจ์ pageParam ๊ฐ ๋ฐํ
});useMutation ํ ์ ์ฃผ๋ก ๋ฐ์ดํฐ ์์ฑ, ์์ , ์ญ์ ์ ๊ฐ์ ๋ณ์ด ์์ ์ ์ฒ๋ฆฌํ ๋ ์ฌ์ฉํฉ๋๋ค. useMutation์ ํตํด ๋น๋๊ธฐ ์์ ์ ์ํํ๊ณ , ํด๋น ์์ ์ ์ํ๋ฅผ ์ถ์ ํ ์ ์์ต๋๋ค.
import { useMutation } from '@tanstack/react-query';
const {
data, // mutationFn ์คํ์ด ์๋ฃ๋์ด ๋ฐํํ ๋ฐ์ดํฐ
error, // mutationFn ์คํ ์ค ๋ฐ์ํ ์๋ฌ ๊ฐ์ฒด
isError, // mutationFn ์คํ ์คํจ ์ฌ๋ถ๋ฅผ ๋ฐํ
isIdle, // mutationFn ์คํ ์ ์ธ์ง์ ๋ํ ์ฌ๋ถ๋ฅผ ๋ฐํ
isPending, // mutationFn ์คํ ๋๊ธฐ์ค์ด๊ฑฐ๋ ์คํ์ค์ธ์ง์ ๋ํ ์ฌ๋ถ๋ฅผ ๋ฐํ
isPaused, // mutationFn ์คํ์ ์ค์ง ์ฌ๋ถ๋ฅผ ๋ฐํ
isSuccess, // mutationFn ์คํ ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋์๋์ง์ ๋ํ ์ฌ๋ถ
failureCount, // mutationFn ์คํ ์คํจํ ํ์
failureReason, // mutationFn ๋ง์ง๋ง์ ์คํ ์คํจํ ์๋ฌ ๊ฐ์ฒด
mutate, // mutate ๋ฉ์๋ ํธ์ถ ์ mutationFn ์คํ
mutateAsync, // mutateAsync ํธ์ถ ์ Promise ๊ฐ์ฒด ๋ฐํํ๋ mutationFn ์คํ
reset, // mutationFn ์คํ ์ํ ์ด๊ธฐํ ๋ฉ์๋(data, error, isSuccess, isError ๋ฑ ์ด๊ธฐํ)
status, // mutationFn ์คํ ์ํ(idle, pending, error, success) ๋ฐํ
submittedAt, // mutationFn ์ฒ์ ์คํ๋ ํ์์คํฌํ ๋ฐํ
variables // ๋ง์ง๋ง mutate ๋ฉ์๋ ํธ์ถ ์ ์ ๋ฌํ ๋ณ์ ๋ฐํ
} = useMutation({
mutationFn, // ์ค์ ๋ณ์ด ์์
์ํํ๋ ํจ์
gcTime, // ๋ณ์ด ์์
์บ์๊ฐ GC ๋๊ธฐ๊น์ง์ ์๊ฐ(๋ฐ๋ฆฌ์ด)
meta, // ๋ณ์ด ์์
์ ์ถ๊ฐ์ ์ผ๋ก ์ ๋ฌํ ๋ฉํ๋ฐ์ดํฐ
mutationKey, // ๋ณ์ด ์์
์ ๊ณ ์ ํ๊ฒ ์๋ณํ๋ ํค ๊ฐ
networkMode, // ๋คํธ์ํธ ์ํ์ ๋ฐ๋ฅธ ๋ณ์ด ์์
์ฒ๋ฆฌ ์ค์
onError, // ๋ณ์ด ์์
์คํจ์ ํธ์ถ๋๋ ์ฝ๋ฐฑ ํจ์. error, variables, context๋ฅผ ์ธ์๋ก ์ ๋ฌ ๋ฐ์ ์คํ
onMutate, // ๋ณ์ด ์์
์คํ ์ ์ ํธ์ถ๋๋ ์ฝ๋ฐฑ ํจ์
onSettled, // ๋ณ์ด ์์
์ฑ๊ณตํ๊ฑฐ๋ ์คํจํ ํ์ ํญ์ ํธ์ถ๋๋ ์ฝ๋ฐฑ ํจ์. data, error, variables, context ์ธ์ ์ ๋ฌ ๋ฐ์ ์คํ
onSuccess, // ๋ณ์ด ์์
์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋ ํ ํธ์ถ๋๋ ์ฝ๋ฐฑ ํจ์. data, variables, context ์ธ์ ์ ๋ฌ ๋ฐ์ ์คํ
retry, // ๋ณ์ด ์์
์คํจํ์ ๋ ์ฌ์๋ํ ํ์
retryDelay, // ๋ณ์ด ์์
์คํจํ์ ๋ ์ฌ์๋ํ๊ธฐ ์ ๋๊ธฐํ ์๊ฐ(๋ฐ๋ฆฌ์ด)
scope, // ๋ณ์ด ์์
๋ฒ์ ์ง์
throwOnError // true ์ค์ ์ ๋ณ์ด ์์
์ค ์๋ฌ ๋ฐ์ํ ๊ฒฝ์ฐ ์๋ฌ๋ฅผ throwํ์ฌ ํธ์ถ์์๊ฒ ์ ๋ฌ
});