[유데미] React Query : React로 서버 상태 관리하기
📍prefetching
유저가 다음 페이지로 넘어가기 전에 미리 데이터 받아와서 매끄럽게 UI 변경하는 것
📍기본적인 사용 흐름 overview
1️⃣패키지 설치
npm i @tanstack/react-query
2️⃣query client 생성
- client는 쿼리와 캐시를 관리
3️⃣QueryProvider 적용
- children에 cache, client config 제공
- query client를 값으로 취함
4️⃣useQuery 훅 사용
- 서버에 쿼리하는 훅
📍QueryProvider
// app.tsx
// import
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
// query client 생성
const queryClient = new QueryClient();
// query client provider로 감싸주면 children이 query 훅 사용 가능
<QueryClientProvider client={queryClient}>
// ...
</QueryClientProvider>
이제 데이터를 필요로하는 컴포넌트인 Posts.tsx 에서 useQuery를 사용하면 됨
📍useQuery
// Posts.tsx
// import
import { useQuery } from "@tanstack/react-query";
// data를 받아와서 이를 map으로 나열할 것이므로 useQuery() 훅을 data에 할당
const { data } = useQuery({
queryKey: ["posts"],
queryFn: fetchPosts,
});
// 임시로 Promise가 resolve 되기 전까지 Loading element 리턴
if (!data) return <h2>Loading...</h2>;
⭐직접 type annotation을 하지 않아도 자연스럽다
useQuery 훅 안에 매개변수로 아래 키를 가진 객체를 구성
- 쿼리 키 : 배열 내에 문자열로 지정하면 됨
- 쿼리 함수 : HTTP 요청을 보낼 비동기 함수
- fetchPosts (사전에 정의한 비동기 함수) 가 resolve 되기 전까지 Loading... 을 반환하게 했지만, react query 에서 이를 지원하는 기능이 있다.
useQuery 객체에서 구조분해할당으로 isLoading을 꺼내 쓰면 된다
📍isLoading
const { data, isError, isLoading } = useQuery({
queryKey: ["posts"],
queryFn: fetchPosts,
});
// promise resolve 전에 아래 코드가 동작
if (isLoading) return <h2>Loading...</h2>;
📍isLoading vs isFetching
isFetching
- 비동기 쿼리 함수(GraphQL or fetch) 가 아직 resolve되기 전 상태
isLoading
- 캐시된 데이터가 없는 isFetching 상태
📍isError
- 3번 요청하고도 에러이면 에러로 판정
- 에러 메시지를 갖는 error 도 있음
const { data, isError, error, isLoading } = useQuery({
queryKey: ["posts"],
queryFn: fetchPosts,
});
if (isLoading) return <h2>Loading...</h2>;
// 런타임에서 타입체크 실행
if (isError && error instanceof Error) {
return (
<>
<h2>Oops, something went wrong</h2>
<p>{error.toString()}</p>
</>
);
}
- error는 디폴트 타입이 unknown이기 때문에 런타임에서 Error의 instance인지 체크해주면 됨
📍useQuery의 다른 기능
https://tanstack.com/query/v4/docs/react/reference/useQuery