2 minute read


리액트 쿼리 개념잡기 (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분 후에는 이미 표시되었던 데이터라도 리페칭 되어야할 것



Updated: