서버의 데이터를 변경할 때 사용합니다.
HTTP POST, PUT, DELETE 요청을 사용할 수 있습니다.
mutationFn은 queryFn처럼 Promise를 리턴하는 비동기 함수입니다.
파라미터를 전달받을 수 있습니다.
mutationFn 파라미터는 useMutation의 리턴값인 mutate 함수의 인자로 전달됩니다.
🔥mutationFn에서는 어떻게 동작할지 정의만 하고, mutate 함수를 통해 나중에 실행되는 것입니다
import { useMutation } from "@tanstack/react-query";
//뮤테이션 했을 때 실행할 함수 등록
const uploadPostMutation = useMutation({
mutationFn: (newPost) => uploadPost(newPost),
},
});
//정의해 둔 mutation이 실행되도록 mutate() 함수를 불러준다.
const handleUploadPost = (newPost) => {
uploadPostMutation.mutate(newPost, {
onSuccess: () => {
toast('포스트가 성공적으로 업로드 되었습니다!');
},
});
};
useMutation()훅을 이용해 새로운 데이터를 추가해 보았습니다. 그런데 캐시에 있는 데이터가 업데이트되지 않아, 새로운 데이터를 확인하려면 새로고침을 해 줬어야 했죠.
쿼리 클라이언트의 invalidateQueries()라는 함수를 사용하면 업로드가 끝난 이후에 자동으로 refetch를 하도록 설정할 수 있습니다.
쿼리를 invalidate하면 해당 쿼리를 통해 받아 온 데이터를 stale time이 지났는지 아닌지에 상관없이 무조건 stale 상태로 만들고, 해당 데이터를 백그라운드에서 refetch하게 됩니다.
(특정 API 호출 후, 데이터를 갱신하고 싶을 때 사용할 수 있습니다.)
쿼리 클라이언트는 useQueryClient() 훅을 사용해서 가져올 수 있고요, 원하는 시점에 queryClient.invalidateQueries() 함수를 실행하면 됩니다.
import { useQueryClient } from '@tanstack/react-query'
const queryClient = useQueryClient();
// ...
queryClient.invalidateQueries();
언제 쿼리를 invalidate해야 할까요? 뮤테이션 객체에는 onMutate, onSuccess, onError, onSettled와 같은 주요 옵션들이 있어서 뮤테이션 사이클에 따라 적절한 동작을 추가할 수 있습니다.
( mutate()함수의 콜백옵션도 위와 같다.)
우리는 onSuccess, 즉 뮤테이션이 성공한 시점에 ['post'] 쿼리를 invalidate해 주는 함수를 콜백으로 등록해 주면 되겠죠. 아래 코드를 추가하면 포스트를 업로드하자마자 업로드된 포스트까지 화면에 잘 보이는 것을 확인할 수 있습니다.
const queryClient = useQueryClient();
// ...
const uploadPostMutation = useMutation({
mutationFn: (newPost) => uploadPost(newPost),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['posts'] });
},
});
useMutation()에 등록된 콜백 함수들은 컴포넌트가 언마운트되더라도 실행이 되지만, mutate()의 콜백 함수들은 만약 뮤테이션이 끝나기 전에 해당 컴포넌트가 언마운트되면 실행되지 않는 특징을 가지고 있다.
따라서 query invalidation과 같이 뮤테이션 과정에서 꼭 필요한 로직은 useMutation()을 통해 등록하고, 그 외에 다른 페이지로 리다이렉트한다든가, 혹은 결과를 토스트로 띄워주는 것과 같이 해당 컴포넌트에 종속적인 로직은 mutate()를 통해 등록해 주면 됩니다.
...
const uploadPostMutation = useMutation({
mutationFn: (newPost) => uploadPost(newPost),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['posts'] });
},
});
const handleUploadPost = (newPost) => {
uploadPostMutation.mutate(newPost, {
onSuccess: () => {
toast('포스트가 성공적으로 업로드 되었습니다!');
},
});
};