首页 > 解决方案 > 反应查询突变打字稿

问题描述

我只是在玩 react-query

用打字稿

我的意思是我做我的第一次尝试

这是正确的方法吗?

const useCreateTodo = () => {
  const queryClient = useQueryClient();
  return useMutation(
    (todo: TodoDto) => axios.post(`${URL}/todos`, todo).then((res) => res.data),
    {
      onMutate: async (newTodo: TodoDto) => {
        // Cancel any outgoing refetches (so they don't overwrite our optimistic update)
        await queryClient.cancelQueries("todos");

        // Snapshot the previous value
        const previousTodos = queryClient.getQueryData("todos");

        // Optimistically update to the new value
        queryClient.setQueryData<TodoDto[] | undefined>("todos", (old) =>
          old ? [...old, newTodo] : old
        );

        // Return a context object with the snapshotted value
        return { previousTodos };
      },
      // If the mutation fails, use the context returned from onMutate to roll back
      onError: (
        err,
        newTodo,
        context:
          | {
              previousTodos: unknown;
            }
          | undefined
      ) => {
        queryClient.setQueryData(
          "todos",
          context ? context.previousTodos : context
        );
      },
      // Always refetch after error or success:
      onSettled: () => {
        queryClient.invalidateQueries("todos");
      },
    }
  );
};

标签: reactjsreact-query

解决方案


乐观更新对于类型推断来说有点棘手。现在在 docs 中有一个针对这种确切情况的示例。

从那个例子:

const addTodoMutation = useMutation(
    newTodo => axios.post('/api/data', { text: newTodo }),
    {
      // When mutate is called:
      onMutate: async (newTodo: string) => {
        setText('')
        // Cancel any outgoing refetches (so they don't overwrite our optimistic update)
        await queryClient.cancelQueries('todos')

        // Snapshot the previous value
        const previousTodos = queryClient.getQueryData<Todos>('todos')

        // Optimistically update to the new value
        if (previousTodos) {
          queryClient.setQueryData<Todos>('todos', {
            ...previousTodos,
            items: [
              ...previousTodos.items,
              { id: Math.random().toString(), text: newTodo },
            ],
          })
        }

        return { previousTodos }
      },
      // If the mutation fails, use the context returned from onMutate to roll back
      onError: (err, variables, context) => {
        if (context?.previousTodos) {
          queryClient.setQueryData<Todos>('todos', context.previousTodos)
        }
      },
      // Always refetch after error or success:
      onSettled: () => {
        queryClient.invalidateQueries('todos')
      },
    }
  )

几个解释:

  • 基本上,您只想在 上设置类型定义onMutate,以便类型推断适用于mutateFn(newTodo推断出的) 以及onError.
  • 添加泛型,getQueryData以便previousTodos输入。你不需要联合undefined- react-query 会为你做这件事。
  • 的功能更新程序setQueryData很棘手,因为它要求您返回一个数组,但old可以是未定义的。我更喜欢使用previousTodos返回的getQueryData

推荐阅读