使用 DnD 套件响应查询:尽管有乐观更新,项目在掉落时仍会瞬间返回原始位置

问题描述 投票:0回答:1

我正在开发一个项目,使用 React Query 和 DnD Kit 来实现拖放功能。然而,当我将一个项目放到新位置时,它会短暂返回到其原始位置,然后再进入新位置。我还使用 DnD Kit 提供的 DragOverlay 功能,并遵循文档中规定的规则。

我目前正在使用 React Query 的 mutate 函数进行乐观更新,并且我尝试过使用 setQueryData 直接更新缓存,但我仍然看到这种闪烁。引入单独的本地状态来管理 DnD 更新可以阻止闪烁,但我更愿意避免为此目的添加额外的状态。

我的目标

我想实现流畅的拖放体验,而不需要重复状态。具体来说,我希望: 避免闪烁并防止项目暂时返回到其原始位置。 仅依靠 React Query 进行更新,而不引入新的本地状态。

我尝试过的:

乐观更新:使用 mutate 和 onMutate 来应用乐观更改。

直接缓存更新:删除后立即调用 setQueryData 以立即反映更改。

有人遇到过类似的问题或找到有效的方法来处理这种情况吗?

我正在使用:

"@dnd-kit/core": "^6.1.0",
"@dnd-kit/sortable": "^8.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@tanstack/react-query": "^5.10.0",
reactjs react-query tanstackreact-query dnd-kit
1个回答
0
投票

我也遇到这个问题了!当我实现状态时,我可以让放置动画起作用,但它破坏了我的 React-Query 用例的整个目的。

这是我的相关代码:

const handleDragEnd = (e: DragEndEvent) => {
    const taskId = e.active.id;
    const priority = e.over?.id as string;
    const task = tasks.find((t) => t.id === Number(taskId));

    if (
      task &&
      priority &&
      Object.values(Priority).includes(priority as Priority) &&
      task.priority !== priority
    ) {
      const newTask: TaskType = {
        ...task,
        priority: priority as Priority,
      };

      updateTaskMutation.mutate(newTask);
    }
  };




const updateTaskMutation = useMutation({
    mutationFn: updateTask,
    onMutate: async (updatedTask) => {
      queryClient.setQueryData<TaskType[]>(["tasks"], (oldData) =>
        oldData?.map((task) => {
          if (task.id === updatedTask.id) {
            return updatedTask;
          } else {
            return task;
          }
        })
      );
    },
  });

        <TaskSection id={Priority.HIGH}>
          {filteredTasks
            .filter((task) => task.priority === "HIGH")
            .map((task) => (
              <Task task={task} key={task.id} />
            ))}
        </TaskSection>
        <TaskSection id={Priority.MEDIUM}>
          {filteredTasks
            .filter((task) => task.priority === "MEDIUM")
            .map((task) => (
              <Task task={task} key={task.id} />
            ))}
        </TaskSection>
        <TaskSection id={Priority.LOW}>
          {filteredTasks
            .filter((task) => task.priority === "LOW")
            .map((task) => (
              <Task task={task} key={task.id} />
            ))}
        </TaskSection>
        {/* it was very difficult to get the drop animation working with how react query handles state. It is one thing I would love to go back and figure out given more time */}
        <DragOverlay>
          {activeTask ? <Task task={activeTask} /> : null}
        </DragOverlay>
© www.soinside.com 2019 - 2024. All rights reserved.