앞서 useMutation() 훅으로 새로운 데이터를 추가했는데, 캐시에 있는 데이터가 업데이트되지 않아 새로고침을 한 후 데이터를 확인해봐야 했다.
이때 쿼리 클라이언트의 invalidateQueries() 함수를 사용할면 업로드 이후 자동 refetch가 이루어진다.
invalidateQueries()는 캐시에 있는 모든 쿼리 혹은 특정 쿼리들을 무효화하는 함수이다. 쿼리를 invalidate 하면 해당 쿼리를 통해 받아온 데이터를 stale time 경과 여부와는 무관하게 무조건 stale 상태로 만들고, 해당 데이터를 백그라운드에서 refetch한다.
쿼리 클라이언트는 useQueryClient() 훅을 사용해 가져올 수 있고, 원하는 시점에 queryClient.invalidateQueries() 함수를 실행하면 된다.
🖥️ import { useQueryClient } from '@tanstack/react-query'
const queryClient = useQueryClient();
// ...
queryClient.invalidateQueries();
쿼리를 invalidate하는 시점은 언제일까?
뮤테이션 객체에는 onMutate, onSuccess, onError, onSettled 같은 주요 옵션들이 있어서
뮤테이션 사이클에 따라 적절한 동작을 추가할 수 있다. onSuccess, 즉 뮤테이션이 성공한 시점에 'post' 쿼리를 invalidate하는 함수를 콜백으로 등록하면 된다.
🖥️ const queryClient = useQueryClient();
// ...
const uploadPostMutation = useMutation({
mutationFn: (newPost) => uploadPost(newPost),
onSuccess: () => {
queryClient.invalidateQuries({ queryKey: ['posts] });
},
});
onSuccess, onError, onSettled 같은 옵션들은 useMutation()뿐 아니라
mutate() 함수에서도 사용할 수 있다. 이때 useMutation()에 등록한 콜백 함수들이 먼저 실행되고, 그 다음에 mutate()에 등록한 콜백 함수들이 실행된다.
🖥️ const uploadPostMutation = useMutation({
mutationFn: (newPost) => uploadPost(newPost),
onSuccess: () => {
console.log('onSuccess in useMutation');
},
onSettled: () => {
console.log('onSettled in useMutation');
},
});
// ...
uploadPostMutation.mutate(newPost, {
onSuccess: () => {
console.log('onSuccess in mutate)
}
})
한 가지 주의할 점은, useMutation()에 등록된 콜백 함수들은 컴포넌트가 언마운트 되더라도 실행되지만,
mutate()의 콜백 함수들은 만약 뮤테이션이 끝나기 전에 해당 컴포넌트가 언마운트되면
실행되지 않는 특징이 있다는 것이다.
따라서 query invalidation 같이 뮤테이션에서 꼭 필요한 로직은
useMutation()을 통해 등록하고, 그 외 다른 페이지로 리다이렉트 한다거나 혹은 결과를 토스트를 띄우는 것처럼, 해당 컴포넌트에 종속적인 로직은 mutate()를 통해 등록하도록 한다.
❓무슨 뜻일까
아무튼 아래 예시처럼 쓴다.
🖥️ const uploadPostMutation = useMutate({
mutationFn: (newPorst) => uploadPost(newPost),
onSucess: () => {
QueryClient.invalidateQueries({
queryKey: ['posts']
});
},
})
const handleUploadPost = (newPost) => {
uploadPostMutation.mutate(newPost, {
onSucess: () => {
toast('포스트가 성공적으로 업로드되었습니다');
}
})
}
포스트가 업로드되는 도중에는 중복 업로드가 되지 않도록 버튼을 비활성화.
뮤테이션에 isPending 값이 존재하는데, uploadPostMutation.isPending을 이용해 구현할 수 있다.
🖥️ const uploadPostMutation = useMutation({
mutationFn: (newPost) => uploadPost(newPost),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['posts']});
},
});
// ...
<button disabled={uploadPostMutation.isPending || !content } type="submit">
업로드
</button>
출처 : 코드잇 ReactQuery