通过修改的数据更新查询内容 Updates From Mutation Responses
当在处理更新了服务器上的对象的修改时,新的对象通常会在更新的响应中自动返回。
我们可以利用修改函数返回的对象,并使用 Query Client 的 setQueryData 方法立即用新数据更新现有的查询,而不是去触发新的数据获取,浪费对已有数据的网络调用:
TypeScript
1const queryClient = useQueryClient();2 3const mutation = useMutation({4 mutationFn: editTodo,5 onSuccess: (data) => {6 queryClient.setQueryData(["todo", { id: 5 }], data);7 },8});9 10mutation.mutate({11 id: 5,12 name: "Do the laundry",13});14 15// 下面的查询将被更新为成功的修改响应16const { status, data, error } = useQuery({17 queryKey: ["todo", { id: 5 }],18 queryFn: fetchTodoById,19});你可能想将 onSuccess 的逻辑绑定到一个可重用的修改中。
为此,你可以创建一个自定义 hook,如下所示:
TypeScript
1const useMutateTodo = () => {2 const queryClient = useQueryClient();3 4 return useMutation(editTodo, {5 // 注意第二个参数是`mutate`函数需要的变量6 onSuccess: (data, variables) => {7 queryClient.setQueryData(["todo", { id: variables.id }], data);8 },9 });10};不可变性
通过setQueryData的更新必须以不可变的方式进行。
不要尝试通过缓存获取的修改的数据直接写入缓存。
这可能在一开始会起一点作用,但是会导致一些细微且无法察觉的 bug。
TypeScript
1queryClient.setQueryData(["posts", { id }], (oldData) => {2 if (oldData) {3 // ❌ do not try this4 oldData.title = "my new post title";5 }6 return oldData;7});8 9queryClient.setQueryData(10 ["posts", { id }],11 // ✅ this is the way12 (oldData) =>13 oldData14 ? {15 ...oldData,16 title: "my new post title",17 }18 : oldData19);