참고 : ‣
1. React Query란?
api로 받아온 데이터 캐싱기능을 쉽게 구현하게 해주는 라이브러리
2. 사용방법
1) QueryClientProvider를 컴포넌트의 최상단에 감싸야 한다.
const queryClient = new QueryClient() export default function App() { return ( <QueryClientProvider client={queryClient}> <Example /> </QueryClientProvider> ) }
이렇게 세팅하면 우선 라이브러리를 사용할 준비를 할 수 있다.
2) useQuery
const { data, isLoading, error } = useQuery(queryKey, queryFn, options)
- data : queryFn을 통해 데이터를 가져오면 이 값으로 반환된다.
- isLoading : 아직 데이터를 가져오지 못해 기다리고 있는 상황
- error : 에러 처리
queryKey
- queryKey를 기반으로 데이터를 캐싱한다(한마디로 캐싱된 데이터를 가리키는 고유한 id라고 보면 됨).
- 문자열, 배열로 지정할 수 있다.
const { data, isLoading, error } = useQuery(['products', id], () => axios.get(`http://.../${id}`));
이렇게 query가 변수에 의존하면 그 변수도 queryKey값에 추가해야 한다.
queryFn
useQuery('products', fetchProducts); useQuery(['products', produtId], () => fetchProductById(productId));
이런식으로 사용하면 된다. Promise를 반환하는 함수를 사용해야 한다!!!
options
- enable(boolean) : 쿼리가 자동으로 실행되지 않게 하는 기능
const { data } = useQuery( ['products', id], () => fetchProductById(id), { enabled: !!id, } ); // id가 존재할 때만 쿼리 요청을 보냄.
- staleTime(number | Infinity, default = 0) : 데이터가
fresh
로 유지되는 시간.
- cacheTime(number | Infinity, default = 5min) : 캐시가 메모리에 남아있는 시간. 이 시간이 지나면 garbage collector에 의해 메모리에서 캐시가 제거된다.
- refetchOnMount(boolean | “always”, default = true) : 데이터가
stale
일 때 마운트마다 refetch실행
- refetchOnWindowFocus(boolean | “always”, default = true) : 데이터가
stale
이고 해당 창이 focus되면 refetch 실행
- onSuccess((data) ⇒ void) : 쿼리 성공시 실행되는 함수
- onError((error) ⇒ void) : 쿼리 실패시 실행되는 함수
- onSettled((data?, error?) ⇒ void) : 성공? → 성공데이터, 실패? → 에러
3. default options
동일한 option을 여러번 사용하거나, 하나의 option을 이용해 통제하고 싶은 경우가 많다.
일일이 코딩해서 세팅하는 과정은 굉장히 번거롭다. 그래서 어떻게 하면 default로 option들을 설정해줄 수 있을까?
const queryClient = new QueryClient({ defaultOptions: { queries: { refetchOnMount: false, refetchOnReconnect: false, refetchOnWindowFocus: false, } } });
이런식으로 처음에 queryClient를 생성할 때 미리 옵션들을 넣어놓고 가면 모든 useQuery에 적용이 되기 때문에 수월하게 해결할 수 있다.
4. useMutation
데이터 create, delete, update시 사용하는 훅이다.
const { data, isLoading, mutate, mutateAsync } = useMutation(mutationFn, options); mutate(variables, { onError, onSettled, onSuccess, });
기본 사용법은 위와 같다.
- mutate :
mutate({ id: new Date(), title: 'Do Laundry' }) // 이런식으로 variable객체 전달
- mutationFn((variables) ⇒ Promise) : api요청 함수. mutate에서 variable객체를 받아온다.
const mutation = useMutation({ mutationFn: (newTodo) => { return axios.post('/todos', newTodo) }, }) // mutate에서 받은 variables가 newTodo
options
- onMutate : mutation함수가 실행되기 전에 실행됨.
- onSuccess : 성공 후 결과를 전달할 때 실행됨.
- onError : mutation이 에러가 발생하면
- onSettled : 성공한 데이터 또는 에러 전달시 실행됨.
5. 강제 refetch
위에 refetch 조건을 많이 제한시키면 필요할 때 데이터를 refetch하기 힘들어질 수 있다.
예를들어 당근마켓같이 사람들이 물건을 판매하려고 올릴 경우 올리자마자 refetch되서 갱신되면 좋은데
개발자가 refetch제약조건을 많이 걸어놓으면 물건을 올려도 refetch가 되지 않을 수 있다.
이를 해결하기 위해 강제 refetch하는 방법을 알아두도록 하자.
useMutation(addProduct, {onSuccess: () => { queryClient.invalidateQueries(queryKeys); },});
- 설명 : addProduct가 실행되고, 성공할 경우 invalidateQueries(해당 쿼리를 오래된 것으로 취급하여 강제 refetch)를 통해 새로 refetch해와서 방금 올린 product의 내용을 볼 수 있게 된다.
6. 총정리
- staleTime 🆚 cacheTime
- staleTIme : staleTime이 지나면 background에서 refetch해와서 자연스러운 변경.(api call은 함)
- cacheTime : cacheTime이 지나면 캐시가 제거되며 refetch되기 때문에 로딩가능성 있음.
- useMutation
- 데이터를 변경하게 될 때 사용하면 된다.
- 강제 refetch를 적절히 사용하자.