[react] 리액트 쿼리 개념잡기
리액트 쿼리 개념잡기 (V3)
아쉽게도 V3 기준임당
Devtools
- React Query의 모든 내부 작동을 시각화하는 데 도움이 되며 문제가 발생하면 디버깅 시간을 절약할 수 있습니다! (라고 한다)
- v4는
$ npm i @tanstack/react-query-devtools작업이 필요하다 - 정말 데이터 패칭 과정을 시각적으로 보는데 도움이 된다. 특히 prefetching을 할 경우 바로 확인이 가능해서 편리하다!
- 개발 환경에서만 작동하는 것도 굉장히 편리하다! (번들에 포함되어있다고 함)
// 사용방법
import { ReactQueryDevtools } from "react-query/devtools";
...
<ReactQueryDevtools /> // 다음 코드를 React 앱에서 가능한 한 높은 곳에 배치하세요. 페이지의 루트에 가까울수록 더 잘 작동합니다! → 라고한다
useQuery
- useQuery는 속성이 정말 많다 (참고)
- useQuery의 속성을 사용하여 에러상태와 로딩상태를 손쉽게 처리할 수 있다!
const { isLoading, isError, data, error } = useQuery('queryKey', queryFn: fetchTodoList); if (isLoading) return <h3>Loading</h3>; if (isError) return <h3>Oops, sorry {error.toString()}</h3>; // status 값도 사용 하능함 if (status === 'loading') { return <span>Loading...</span> } - isFetching VS isLoading (속성)
- isFetching은 비동기 쿼리가 해결되지 않았음을 의미함 → fetching을 완료하지 않았음을 의미 (쿼리가 axios호출이나 graphQL호출일수도,,,)
- isLoading은 가져오는 상태에 있음을 의미함 → 쿼리함수가 아직 해결되지 않았음을 의미 → 그리고 캐시된 데이터도 없음 (데이터 가져오는 중이고 캐시 데이터도 없다는 것) / isFetching이 true일 경우임
- isFetching이 isLoading보다 큰 개념!
queryKey
- React Query는 쿼리 키를 기반으로 쿼리 캐싱을 관리합니다. → 라고 한다!
- 쿼리 키는 유일한 값을 가져야 하기 때문에 다르게 정해줘야 함
- 예로 댓글을 불러오는 경우 쿼리 키 값이 동일하면 같은 댓글만 불러와지기 때문에 다르게 설정해줘야 하는데 이때 의존성 배열을 추가할 수 있다.
- useQuery([“comments”, post.id]) 와 같이 배열에 추가해주면 유일한 값을 가질 수 있게 된다!
- 쿼리 키가 변경됐을때 useQuery hook은 쿼리를 반복한다! 그래서 데이터 함수가 바뀌면 쿼리 키도 바뀌게 됨!
(V4 부터 쿼리키는{ queryKey : [something...]}으로 변경되었다!)
Prefetching
- prefetchQuery메서드를 사용하여 캐시에 넣을 쿼리 결과를 미리 가져올 수 있습니다. → 라고 한다!
- 페이지네이션을 할 경우 데이터를 패칭하는 로딩시간이 있기 떄문에 나쁜 사용자 경험을 줄 수 있다.
- 페이지 이동시 로딩을 방지하기 위해 미리 패칭 해 놓을 수 있는데
import { useQueryClient } from "react-query"; ... queryClient.prefetchQuery(["posts", nextPage], () => fetchPosts(nextPage) ); - 다음 페이지의 내용을 미리 패칭해준다.
- 이때 쿼리키의 의존성 배열에 nextPage이 들어가는데 이유는 이미 있는 캐시 데이터인 경우 패칭해줄 필요가 없기 떄문이다!
- 캐시 데이터를 잘 판별하기 위해서 쿼리키 지정을 신경써줘야할 것 같다!
mutate
import { useQuery, useMutation } from "react-query";
...
const deleteMutation = useMutation((postId) => deletePost(postId)); // 삭제하는 함수를 실행해준다!
...
{deleteMutation.isLoading && (<p>Deleting the post</p>)}
- 굉장히 간단한 사용법이다
- 낙관적 업데이트에 유용하다!
- 반환값에 상태를 확인하여 여러가지 처리를 할 수 있고 성공시 처리한 데이터를 그대로 반영해준다
- useMutate → mutate 함수를 반환한다.
- 쿼리키를 필요로 하지 않는다. 데이터를 저장하지 않는 mutation이기 떄문!
- isFetching이 존재하지 않는다! 캐시는 존재하지 않고 재시도 또한 기본값으로 존재하지 않음 (원래는 에러 발생 시 기본 3회 재시도)
staleTime vs cacheTime
- staleTime은 데이터를 허용하는 최대시간! (데이터의 성격에 따라 달라질 것)
- 데이터가 만료되지 않으면 리페칭이 일어나지 않음 (즉 staletime 이후에 리페칭이 일어난다는 의미)
- staleTime은 기본값이 0이다 → 데이터가 늘 최신 상태를 유지하는 것
- cache는 나중에 필요할 수도 있는 데이터
- cacheTime은 기본값이 5분이다 → 5분 후에는 이미 표시되었던 데이터라도 리페칭 되어야할 것