본문 바로가기

React/Hooks

React Query 기본

리액트 쿼리를 제대로 쓰기 위해 작동하는 기본 원리를 다룬다.

Stale이란

리액트 쿼리는 기본적으로 캐시된 데이터를 stale한 상태로 여긴다.
stale이란 최신화가 필요한 데이터라는 의미로
stale한 상태가 되면 다음의 경우에 refetch 된다.

 

- 새로운 query 인스턴스가 마운트될 때
  (useQuery가 처음 호출될 때, Whenever a new component that calls useQuery mounts, React Query will do a revalidation)

- 브라우저 화면을 이탈했다가 다시 포커스할 때

- 네트워크가 다시 연결될 때

- 특별히 설정한 refetch interval에 의해서 (refetchInterval) 

 

refetchOnWindowFocus 옵션 등으로 기본 refetch 설정을 막을 수 있고
staleTime 옵션으로 설정한 시간 동안 데이터가 stale 되지 않도록 해 refetch를 막을 수도 있다.

query에 별다른 action이 없으면 inactive 상태로 캐시에 남아 있다가 5분 뒤에 메모리에서 사라진다.
cacheTime 옵션을 설정해서 이 시간을 조정할 수 있다.

 

참고 : react-query.tanstack.com/guides/important-defaults

 

Caching이 왜 안 될까?

리액트 쿼리에 아무 설정을 하지 않으면 캐싱이 되지 않는다.

캐싱을 제대로 쓰려면 staleTime과 cacheTime에 대해 알아야 한다.

두 값은 options에 넣을 수 있다.

 

const { data } = useQuery('users', getUsers, { // options
  staleTime: 5000,
  cacheTime: Infinity,
});

 

staleTime으로 설정한 시간만큼 api 요청한 데이터의 신선도가 유지되고

이 시간이 지나면 fresh한 상태에서 stale한 상태 곧 썩기 때문에 

같은 데이터를 다시 필요로 할 때 api 요청을 다시 할 수밖에 없다.

 

그러나 아무리 staleTime을 길게 줬다해도

저장되는 시간인 cacheTime이 짧다면

데이터가 사라지기 때문에 다시 요청을 해야 한다.

 

staleTime의 기본값은 0이고 cacheTime은 5분이다.

때문에 아무 option을 주지 않으면 캐싱이 되지 않는다.

데이터는 캐싱되지만 신선한 데이터가 하나도 없는 것이기 때문이다.

 

보다 자세하게 동작원리를 알고 싶다면 dev 툴로 연습해보자.

https://react-query.tanstack.com/devtools

 

데이터의 상태를 쉽게 확인할 수 있다.

useQuery

useQuery의 첫 번째 인자에는 unique key가 들어간다.
이 키는 내부적으로 refetching, caching, query 공유를 위해 사용된다.

api 요청으로 얻은 데이터를 구분할 수 있는 key를 부여해서
또다시 같은 데이터를 요청하지 않도록 할 수 있다.
useQuery의 key가 달라지면 곧바로 다시 api 요청을 한다.

두 번째 인자에는 data를 resolve 하거나 error를 뱉는 Promise를 리턴하는 함수를 넣는다.
이 함수 안에서 에러가 발생하면 자동으로 error를 reject 해준다.
axios는 200이 아닌 응답에 에러가 발생하기 때문에 별다른 처리를 해주지 않아도 되지만
fetch를 쓸 경우에는 일일이 throw new Error()를 해줘야 한다.

데이터를 리프레쉬 해야할 때

포스트 요청을 하거나 삭제 요청을 했을 때 화면에 보여주는 데이터에 변화를 줘야 한다.
그러나 query 키가 변하지 않으므로 강제 리프레쉬를 해야할 필요가 있다.
이런 때에는 queryClient의 invalidateQueries 메소드를 이용해서 query 키를 날려버린다.

 

 // Invalidate every query in the cache 
 queryClient.invalidateQueries() 
 // Invalidate every query with a key that starts with `todos` 
 queryClient.invalidateQueries(['todos', 'something'])


참고 : react-query.tanstack.com/guides/query-invalidation