Docs
GUIDES & CONCEPTS
Updates from Mutation Responses

Updates from Mutation Responses

서버에서 객체를 업데이트하는 뮤테이션을 처리할 때, 새 객체가 뮤테이션 응답에서 자동으로 반환되는 것이 일반적입니다. 이미 가지고 있는 데이터에 대해 네트워크 호출을 낭비하는 대신, 뮤테이션 함수가 반환한 객체를 활용하여 기존 쿼리를 새 데이터로 즉시 업데이트할 수 있습니다. 이를 위해 Query Client의 setQueryData 메서드를 사용할 수 있습니다:

const queryClient = useQueryClient();
 
const mutation = useMutation({
  mutationFn: editTodo,
  onSuccess: (data) => {
    queryClient.setQueryData(["todo", { id: 5 }], data);
  },
});
 
mutation.mutate({
  id: 5,
  name: "Do the laundry",
});
 
// 아래 쿼리는 성공적인 뮤테이션의 응답으로 업데이트됩니다
const { status, data, error } = useQuery({
  queryKey: ["todo", { id: 5 }],
  queryFn: fetchTodoById,
});

재사용 가능한 뮤테이션에 onSuccess 로직을 통합하고 싶다면, 다음과 같은 커스텀 훅을 만들 수 있습니다:

const useMutateTodo = () => {
  const queryClient = useQueryClient();
 
  return useMutation({
    mutationFn: editTodo,
    // 두 번째 인자는 `mutate` 함수가 받는 변수 객체입니다
    onSuccess: (data, variables) => {
      queryClient.setQueryData(["todo", { id: variables.id }], data);
    },
  });
};

Immutablity

setQueryData를 통해 업데이트할 때는 불변 방식으로 수행해야 합니다. 절대 캐시에서 가져온 데이터를 직접 수정하려고 하지 마세요. 처음에는 잘 작동할 수 있지만, 이후에 미묘한 버그를 유발할 수 있습니다.

queryClient.setQueryData(["posts", { id }], (oldData) => {
  if (oldData) {
    // ❌ 이렇게 시도하지 마세요
    oldData.title = "my new post title";
  }
  return oldData;
});
 
queryClient.setQueryData(
  ["posts", { id }],
  // ✅ 이 방법을 사용하세요
  (oldData) =>
    oldData
      ? {
          ...oldData,
          title: "my new post title",
        }
      : oldData
);