일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 잠실새내 도그존
- 앙버터마카롱
- 지보싶 신촌점
- graphql with RN
- 운정 소바동
- apollo react native
- 비동기배열처리방법
- 잠실새내
- 신촌 소문난집
- promise처리
- 예쁜술집 예술
- apolloclient
- promise메서드
- graphql mutation error
- 홍대 토라비
- graphql with reactnative
- useMutation error
- 화이트해커를 위한 웹 해킹의 기술
- graphql
- 토라비
- 도그존
- graphql 400
- 비동기배열
- 금별맥주
- 고르드
- graphql react native
- 화이트 해커를 위한 웹 해킹의 기술
- typescript
- 홍대 예술
- 홍대 카페 장쌤
- Today
- Total
yehey's 공부 노트 \n ο(=•ω<=)ρ⌒☆
[Next js/react-query] react query 설치 및 적용하기 본문
Today I Learned
: React query 라이브러리를 Next js 에 적용하고 사용해보았다.
배경
프로젝트 진행 중 서버와 api 통신 과정을 react query + axios를 이용하여 진행하기로 하였다. fetch 가 Next 공식 문서 상에 있지만 기본 url 정보나 인터셉터 등등을 지정해놓고 사용하기에는 axios 가 더 적절하다고 판단했다. 굳이 react query를 사용한 이유는 서버 데이터 관리, 캐싱 등을 통해 성능을 높일 수 있다고 생각하여 한번 적용해보고자 했다. 동일한 데이터 요청을 중복으로 처리하지 않고 기존 응답 값을 캐싱하고 캐싱 값을 사용한다는 점에서 시도해볼 가치가 있다고 생각해서 적용했다. 그리고 무엇보다 hook 과 비슷한 구조를 가지고 있어서 초기 학습은 어렵지 않아서 좋았다. (초기만 안어렵고 잘 쓰기는 결국 어려운 듯...)
무엇보다 devtool 이 잘 되어있어서 좋았다!! 역시 눈으로 보는게 훨씬 이해가 잘 간다.
Contents
react query 설치
npm install @tanstack/react-query
npm install @tanstack/react-query-devtools
// utils/ReactQueryProvider.tsx
'use client';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental';
import React from 'react';
function ReactQueryProvider({ children }: React.PropsWithChildren) {
const [queryClient] = React.useState(
() =>
new QueryClient({
defaultOptions: { queries: { staleTime: 5000 } },
}),
);
return (
<QueryClientProvider client={queryClient}>
<ReactQueryStreamedHydration>{children}</ReactQueryStreamedHydration>
<ReactQueryDevtools />
</QueryClientProvider>
);
}
export default ReactQueryProvider;
Next js Approuter 를 사용했다.
// app/layout.tsx
export default function RootLayout({ children }: IRootLayoutProps) {
return (
<html lang="kr">
<body>
<div id="portal" />
<ReactQueryProvider>{children}</ReactQueryProvider>
</body>
</html>
);
}
이제 react query 사용 준비는 끝났다.
Example / Practice
useQuery
const { data: selectableTagList,isLoading,isError } = useQuery({
queryKey: ['rootTag', typeID],
queryFn: () => getRootTagList(typeID),
});
react hook을 사용하는 것처럼 사용할 수 있다. queryKey 를 기반으로 값을 캐싱하기 때문에 적절한 queryKey를 입력하는 것이 중요할 것 같다.
useSuspenseQuery
const { data: statisticList } = useSuspenseQuery({
queryKey: ['statisticList', filter.archiveTypeID, filter.start, filter.end],
queryFn: () => getRootTagStatisticListByArchiveType(filter),
});
이전 버전에서는 useQuery 에 suspense:true
옵션을 주고 Suspense와 함께 사용했는데, v5 부터는 useSuspenseQuery를 통해 suspense와 사용할 수 있다.
function StatisticPage() {
return (
<Layout>
<Suspense fallback={<Loading />}>
<Statistic />
</Suspense>
</Layout>
);
}
위와 같이 Suspense 로 감싸주면 사용할 수 있다.
useMutation
const { mutate } = useMutation({
mutationFn: (data: LedgerCreateParams) => postLedger(data),
onSuccess: () => {
alert('내역 저장 완료');
setForm(defaultForm);
},
onError: () => {
alert('내역 저장 실패');
},
});
mutate 동작을 원하는 이벤트 핸들러에 넣어주면 된다.
useQueries
병렬적으로 쿼리를 수행하고 싶을 때 사용할 수 있다.
export const useChildTagList = (tagList: number[]) => {
const [childTagList, setChildTagList] = useState<TagType[]>([]);
const queryResult = useQueries({
queries: tagList.map((tag) => {
return { queryKey: ['childTag', tag], queryFn: () => getChildTagList(tag) };
}),
combine: (results) => {
return {
data: results.map((result) => {
return result.data;
}),
pending: results.some((result) => result.isPending),
};
},
});
combine 함수에서 data 를 반환하도록 추가할 수 있다. 데이터를 사용할 때는 queryResult.data
로 사용할 수 있다.
https://github.com/TanStack/query/discussions/2440 안정적인 success 이후 데이터를 가져오도록 하는 방법도 있다.
invalidateQueries 쿼리 무효화
특정 mutation 이후에 다른 query 를 동시에 업데이트 하고 싶을 때 사용했다. 강제로 쿼리를 최신 상태로 만들어준다. 쿼리가 무효화되기 때문에 최신상태 쿼리를 다시 get 하는 방식으로 추정.. key를 기반으로 무효화하기 때문에 관련 쿼리가 모두 무효화된다는 점을 주의..
const queryClient = useQueryClient();
const { mutate } = useMutation({
mutationFn: (data: TagCreateParams) => postTag(data),
onSuccess: () => {
setTagForm(defaultForm);
if (tagForm.parentID) {
queryClient.invalidateQueries({ queryKey: ['childTag', tagForm.parentID] });
}
queryClient.invalidateQueries({ queryKey: ['rootTag', tagForm.archiveTypeID] });
closeModal();
},
onError: () => {
alert('태그 생성 실패');
},
});
비슷하게 setQueryData도 있는데, 이건 아직 사용해보지 않았다. 쿼리를 완전 무효화하는게 아니라 즉시 업데이트 한다는 점이 차이인 듯
Learned
react query를 사용해보며 처음에는 graphql, apollo client 랑 크게 다를 것 없다고 생각했는데 기능적으로 완전히 달랐다. 그치만 graphql 덕에 활용 자체가 어렵진 않았다. devtools 를 통해서 캐시데이터 상태를 확인하니 이해에 더 도움이 됐다. 그치만 아직은 부족함,,,,,
What I Will Study
정리한 부분은 진짜 기본 사용 정도라서 관련 react query 옵션이나 함수들을 찾아서 잘 쓰고싶다.
stale time 이나 cache, refetch 등등 많던데 꼭 잘 써봐야징
참조
https://github.com/ssi02014/react-query-tutorial
https://tanstack.com/query/v5/docs/react/overview
'개발 > 프로젝트' 카테고리의 다른 글
[Next js] recoil 전역 상태관리 적용하기 (0) | 2024.01.17 |
---|---|
[BE/spring boot] JPA ManyToMany 테이블 수정하기 (1) | 2024.01.07 |
[FE/next js] 프론트 스택 정하기 및 next js 설치 (app router) (0) | 2023.12.17 |
[BE/spring boot] custom Response DTO 만들기 (0) | 2023.12.15 |
[BE/spring boot] JAVA 설치 및 스프링 부트 서버 세팅 (1) | 2023.12.06 |