乐观更新 optimistic-updates
在执行修改之前打算进行乐观更新时,修改有可能失败(可能性非零)。 在大多数失败的情况下,您可以轻松地为乐观查询触发重新获取,使其恢复到真正的服务器状态。 但是在某些情况下,重新获取可能不能正确工作,修改可能会导致某种服务器端的问题,使其无法进行。 在这种情况下,您可以选择回滚您的更新。
为此,useMutation 的 onMutate 回调允许您返回一个值,该值稍后将作为最后一个参数传递给 onError 和 onSettled 处理。
在大多数情况下,以这种方式来传递回滚函数是最有用的。
添加新的 todo 时更新 todos 列表
JavaScript
1const queryClient = useQueryClient();2 3useMutation(updateTodo, {4 // 当 mutate 调用时5 onMutate: async (newTodo) => {6 // 撤销相关的查询(这样它们就不会覆盖我们的乐观更新)7 await queryClient.cancelQueries("todos");8 9 // 保存前一次状态的快照10 const previousTodos = queryClient.getQueryData("todos");11 12 // 执行乐观更新13 queryClient.setQueryData("todos", (old) => [...old, newTodo]);14 15 // 返回具有快照值的上下文对象16 return { previousTodos };17 },18 // 如果修改失败,则使用 onMutate 返回的上下文进行回滚19 onError: (err, newTodo, context) => {20 queryClient.setQueryData("todos", context.previousTodos);21 },22 // 总是在错误或成功之后重新获取:23 onSettled: () => {24 queryClient.invalidateQueries("todos");25 },26});更新单个的 todo
JavaScript
1useMutation(updateTodo, {2 // 当 mutate 调用时3 onMutate: async (newTodo) => {4 // 取消相关的获取数据逻辑(这样它们就不会覆盖我们的乐观更新)5 await queryClient.cancelQueries(["todos", newTodo.id]);6 7 // 保存前一次状态的快照8 const previousTodo = queryClient.getQueryData(["todos", newTodo.id]);9 10 // 执行乐观更新11 queryClient.setQueryData(["todos", newTodo.id], newTodo);12 13 // 返回具有快照值和修改值的上下文对象14 return { previousTodo, newTodo };15 },16 // 如果修改失败,则使用 onMutate 返回的上下文17 onError: (err, newTodo, context) => {18 queryClient.setQueryData(19 ["todos", context.newTodo.id],20 context.previousTodo,21 );22 },23 // 总是在错误或成功之后重新获取:24 onSettled: (newTodo) => {25 queryClient.invalidateQueries(["todos", newTodo.id]);26 },27});如果你愿意,你也可以使用 onsettled 函数来代替 onError 和 onSuccess 处理:
JavaScript
1useMutation(updateTodo, {2 // ...3 onSettled: (newTodo, error, variables, context) => {4 if (error) {5 // do something6 }7 },8});