typescript 如何在使用React Query多次重取时保留以前的数据?

cclgggtu  于 2023-08-07  发布在  TypeScript
关注(0)|答案(1)|浏览(96)

我已经实现了一个自定义的React钩子,在我的API上创建一个任务,将任务UUID存储在状态中,然后每2秒开始轮询API,直到收到成功的数据。
我面临的问题是,我想显示API在获取或重新获取新数据时返回的 * 最后一次成功的数据 *。现在,当调用mutate时,查询结果是undefined。我不想那样
API现在很慢,大约需要 *12秒或6次重新获取 * 才能成功完成请求,所以我想同时显示旧数据。我想你现在明白我想说的了。
您可以忽略sendToBackground(),它是您使用Plasmo与后台服务工作人员进行通信的方式。

我使用的工具:

  • Plasmo 0.81.0
  • React 18.2.0
  • React查询^3.39.3

use-suggestions.ts

export function useSuggestions(
  text: string,
  id: string,
): UseQueryResult<TaskTextStatus> {
  const [task, setTask] = useState<string>();
  const [stopRefetch, setStopRefetch] = useState(false);
  const [textDebounced] = useDebounce(text, 1000);

  // Triggers on input text change, calls mutate once per 1000ms
  useEffect(() => {
    mutate(text);
  }, [textDebounced]);

  // Submits text task to API, stores task UUID in `task` state
  const { mutate } = useMutation(
    ["suggestions", id, text],
    async (text: string) => {
      if (!text) return;
      const res = await sendToBackground<{ text: string }, TaskTextSubmit>({
        name: "send-text",
        body: { text },
      });
      return res;
    },
    {
      onSuccess(data) {
        if (!data) return;

        // Sets the created task UUID
        setTask(data.task_uuid);
      },
      onError(e) {
        console.log(e, "ERROR");
      },
    },
  );

  // Activates when task_uuid is known(when task is created)
  // Polls the API every 2 seconds in the background
  // Stops when receives result
  return useQuery(
    ["suggestions", id, text],
    async () => {
      if (!task) return;
      setStopRefetch(false);
      const res = await sendToBackground<{ task_uuid: string }, TaskTextStatus>(
        { name: "check-task", body: { task_uuid: task } },
      );

      if (res.is_success) return res;
    },
    {
      enabled: !!task,
      refetchInterval: stopRefetch ? false : 2000,
      keepPreviousData: true,
      refetchIntervalInBackground: true,
      refetchOnWindowFocus: false,
      onSuccess(data) {
        if (data?.is_success) {
          setStopRefetch(true);
          setTask("");
        }
      },
      onError() {
        setStopRefetch(true);
      },
    },
  );
}

字符串
添加keepPreviousData后,它在第一次提取后返回旧数据。然后它设置为undefined,因为没有从以下重新获取返回数据。
本质上,我需要保留is_success为真的最后一个数据,直到接收到is_success也为真的新数据,避免在重新获取过程中发生的所有事情。
希望我没有把它弄得太混乱,谢谢你的帮助!

kpbwa7wx

kpbwa7wx1#

一些反馈:

  • 当fetch不成功时,应该抛出错误
  • data不会因为最近的读取出错而被清除,因此即使error存在,也要向用户显示data
  • keepPreviousData: true并不能解决你的问题,这意味着数据将在提取过程中保留 * 当查询键更改 *。因此,在您的示例中,如果id1更改为2,则在2获取时,将向用户显示来自1的数据。考虑一下你是否真的需要它。
  • 从状态中删除stopRefetch。如果你真的想暂停或禁用查询,请将enabled设置为false

更新后的queryFn可能如下所示:

async () => {
  const res = await sendToBackground<{ task_uuid: string }, TaskTextStatus>(
    { name: "check-task", body: { task_uuid: task } },
  );

  if (!res.is_success) { throw new Error('Fetch not successful') }

  return res;
},

字符串

相关问题