Skip to main content

通过修改的数据更新查询内容 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 的逻辑绑定到一个可重用的修改中。 为此,你可以创建一个自定义 hook,如下所示:

const useMutateTodo = () => {
const queryClient = useQueryClient();

return useMutation(editTodo, {
// 注意第二个参数是`mutate`函数需要的变量
onSuccess: (data, variables) => {
queryClient.setQueryData(["todo", { id: variables.id }], data);
},
});
};

不可变性

通过setQueryData的更新必须以不可变的方式进行。 不要尝试通过缓存获取的修改的数据直接写入缓存。 这可能在一开始会起一点作用,但是会导致一些细微且无法察觉的 bug。

queryClient.setQueryData(["posts", { id }], (oldData) => {
if (oldData) {
// ❌ do not try this
oldData.title = "my new post title";
}
return oldData;
});

queryClient.setQueryData(
["posts", { id }],
// ✅ this is the way
(oldData) =>
oldData
? {
...oldData,
title: "my new post title",
}
: oldData
);