Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
Tags
- nextjs
- NextAuth
- textarea autosize
- aws lightsail
- next.js
- 정렬
- 버블정렬
- 스택
- JavaScript
- 해쉬
- 그리디
- isNaN
- 투포인터
- js알고리즘
- TypeScript
- 라이프사이클
- styled-components
- react-query
- 큐
- cookie
- 슬라이딩윈도우
- 빅오
- 블로그만들기
- Algorithm
- typscript
- never타입
- tailwindcss
- nestjs
- 알고리즘
- react
Archives
- Today
- Total
far
[React-Query] 기본적인 것들 본문
1. Query-Key
- Query-Key란?
Query-Key는 쿼리를 고유하게 식별하기 위한 키로, 데이터를 캐싱하거나 새로고침할지, 캐시에서 데이터를 사용할지를 결정한다. 보통 배열 형태로, 리소스 이름과 파라미터를 포함하여 사용한다. 예를 들어, ['todos', userId]처럼 설정할 수 있다. - Next.js 서버사이드에서의 Query-Key 사용
서버에서 Query-Key를 설정해 데이터를 미리 가져오고, React Query가 이를 캐싱해 활용할 수 있다.
// app/layout.tsx
import { ReactQueryProvider } from './_providers';
import './globals.css';
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html>
<body>
<ReactQueryProvider>
<main>{children}</main>
</ReactQueryProvider>
</body>
</html>
);
}
import { dehydrate, HydrationBoundary, QueryClient } from '@tanstack/react-query';
export default async function page() {
const queryClient = new QueryClient();
await queryClient.prefetchQuery({ queryKey: ['key'] queryFn: getAPI });
const dehydratedState = dehydrate(queryClient);
const data = await getAPI({ queryKey: ['key'] });
return (
<HydrationBoundary state={dehydratedState}>
<Component data={data} />
</HydrationBoundary>
);
page.tsx에서 HydrationBoundary를 감싸 사용할 수 있다.
2. Mutations에서 mutationKey 사용하기
- Mutation-Key란?
Mutation-Key는 Query-Key와 비슷하게, mutation의 유형을 구분할 때 사용한다. 여러 종류의 mutation을 추적하거나 디버깅할 때 유용하다.
'use client';
const { mutate } = useMutation({
mutationKey: ['todos', 'add'],
mutationFn: newTodo => axios.post('/api/todos', newTodo),
onSuccess: () => {
queryClient.invalidateQueries(['todos']);
}
});
3. invalidateQueries를 사용한 쿼리 무효화
- 왜 invalidateQueries가 필요한가?
mutation이 성공하면, React Query의 invalidateQueries로 관련 쿼리를 무효화하여 최신 데이터를 자동으로 가져오게 할 수 있다. 예를 들어, 새로운 Todo를 추가한 후에 ['todos'] 쿼리를 무효화해 목록이 업데이트되도록 한다.
const queryClient = useQueryClient();
const { mutate } = useMutation({
mutationFn: newTodo => axios.post('/api/todos', newTodo),
onSuccess: () => {
queryClient.invalidateQueries(['todos']);
}
});
4. 무한 스크롤: useInfiniteQuery vs SuspenseInfiniteQuery
- useInfiniteQuery
자동 페이지네이션을 지원하여 사용자가 스크롤할 때 데이터를 연속으로 불러온다. getNextPageParam 함수를 통해 다음 페이지가 있는지 판단한다.
'use client';
const {
data,
fetchNextPage,
hasNextPage,
isFetchingNextPage,
} = useInfiniteQuery({
queryKey: ['todos'],
queryFn: ({ pageParam = 1 }) => fetchTodos(pageParam),
getNextPageParam: (lastPage) => lastPage.nextCursor,
initialPageParam: 1, // 1페이지부터 시작 (초기 값, v5부터 적용)
});
- SuspenseInfiniteQuery
Suspense를 활용하여 무한 스크롤을 감싸 UX적으로 더 좋다고 한다. React 18 이상에서 Suspense를 통해 로딩과 에러 상태를 처리한다. enabled는 사용 불가능하다
'use client';
const SuspenseInfiniteScroll = () => (
<Suspense fallback={<LoadingSpinner />}>
<InfiniteQueryComponent />
</Suspense>
);
const {
data,
fetchNextPage,
hasNextPage,
isFetchingNextPage,
} = useSuspenseInfiniteQuery({
queryKey: ['todos'],
queryFn: ({ pageParam = 1 }) => fetchTodos(pageParam),
getNextPageParam: (lastPage) => lastPage.nextCursor,
initialPageParam: 1, // 1페이지부터 시작 (초기 값, v5부터 적용)
});
5. Optimistic Updates
- Optimistic Updates
UI를 서버 응답 전에 업데이트해 사용자로 하여금 반응이 빠르게 느껴지도록 한다.
const { mutate } = useMutation({
mutationFn: updateTodo,
onMutate: async newTodo => {
await queryClient.cancelQueries(['todos']);
const previousTodos = queryClient.getQueryData(['todos']);
queryClient.setQueryData(['todos'], old => [...old, newTodo]);
return { previousTodos };
},
onError: (err, newTodo, context) => {
queryClient.setQueryData(['todos'], context.previousTodos);
},
onSettled: () => {
queryClient.invalidateQueries(['todos']);
}
});
- Pre-Fetching Data
서버사이드에서 queryClient.prefetchQuery를 사용해 데이터를 사전에 가져온다.
'use server';
const queryClient = getQueryClient();
await queryClient.prefetchQuery(['todos'], fetchTodos);
const dehydratedState = dehydrate(queryClient);
- Query Caching 및 갱신 전략
staleTime을 설정하여 자주 사용하는 데이터는 일정 시간 동안 새로고침 없이 사용하도록 최적화할 수 있다. - 오류 처리와 리트라이
쿼리의 retry 옵션을 통해 특정 횟수만큼 자동으로 재시도하거나 에러를 사용자에게 알릴 수 있다.
- ESLint
@tanstack/eslint-plugin-query/recommended는 쿼리 키의 유효성 검사, 잘못된 staleTime 사용 방지 등을 자동으로 체크해준다.
// eslintrc.json
{
"extends": ["plugin:@tanstack/eslint-plugin-query/recommended"]
}
Comments