当处理 更新 服务器上对象的 mutations (突变) 时,通常新对象会自动在 mutation (突变) 的响应中返回。与其为该项目重新获取任何 queries (查询) 并浪费网络调用来获取我们已经拥有的数据,不如利用 mutation (突变) 函数返回的对象,并使用 Query Client 的 setQueryData 方法立即使用新数据更新现有 query (查询)
const queryClient = useQueryClient()
const mutation = useMutation({
mutationFn: editTodo,
onSuccess: (data) => {
queryClient.setQueryData(['todo', { id: 5 }], data)
},
})
mutation.mutate({
id: 5,
name: 'Do the laundry',
})
// The query below will be updated with the response from the
// successful mutation
const { status, data, error } = useQuery({
queryKey: ['todo', { id: 5 }],
queryFn: fetchTodoById,
})
const queryClient = useQueryClient()
const mutation = useMutation({
mutationFn: editTodo,
onSuccess: (data) => {
queryClient.setQueryData(['todo', { id: 5 }], data)
},
})
mutation.mutate({
id: 5,
name: 'Do the laundry',
})
// The query below will be updated with the response from the
// successful mutation
const { status, data, error } = useQuery({
queryKey: ['todo', { id: 5 }],
queryFn: fetchTodoById,
})
你可能想将 onSuccess 逻辑绑定到可重用的 mutation (突变),为此你可以创建一个像这样的自定义 Hook
const useMutateTodo = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: editTodo,
// Notice the second argument is the variables object that the `mutate` function receives
onSuccess: (data, variables) => {
queryClient.setQueryData(['todo', { id: variables.id }], data)
},
})
}
const useMutateTodo = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: editTodo,
// Notice the second argument is the variables object that the `mutate` function receives
onSuccess: (data, variables) => {
queryClient.setQueryData(['todo', { id: variables.id }], data)
},
})
}
通过 setQueryData 进行的更新必须以不可变的方式执行。不要尝试通过就地改变数据(你从缓存中检索的数据)直接写入缓存。它可能一开始有效,但可能会导致后续出现细微的错误。
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,
)
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,
)