首页 > 解决方案 > 设置状态对象以重新获取时反应查询隐藏错误消息

问题描述

在当前的 React 查询中,我正在调用 api,当出现错误时,它会显示错误,但是,当我更改状态对象以进行新调用时,它确实显示加载数据但不隐藏错误消息?我创建了一个示例,我添加了一个按钮,该按钮会给出错误消息,即

stackblitz 示例:https ://stackblitz.com/edit/react-ts-6wugxj?file=index.tsx

import React from 'react';
import { render } from 'react-dom';
import { useQuery } from 'react-query';
import axios from 'axios';
import { QueryClient, QueryClientProvider } from 'react-query';

const App: React.FunctionComponent = () => {
  const queryKey = 'getData';

  const [number, setNumber] = React.useState(1)

  const getData = async (): Promise<any> => {
    await new Promise((resolve) => setTimeout(resolve, 1000));
    const response = await axios
      .get(`https://jsonplaceholder.typicode.com/posts/${number}`)
      .then((res) => res.data);
    return response;
  };

  const {
    data: result,
    isFetching,
    status,
    error,
    refetch,
  }: any = useQuery(queryKey, getData, {
    refetchOnWindowFocus: false,
    staleTime: 0,
    cacheTime: 0,
    refetchInterval: 0,
  });

  React.useEffect(() => {
    refetch();
}, [number, refetch]);

  return (
    <div className="Container">
      <button onClick={refetch}>Refetch query</button>
      <button onClick={() => setNumber(() => 1)}>Get 1</button>
      <button onClick={() => setNumber(() => 2)}>Get 2</button>
      <button onClick={() => setNumber(() => 3)}>Get 3</button>
      <button onClick={() => setNumber(() => 99999)}>Get 99999</button>
      {status === 'error' && <div className="mt-5">{error.message}</div>}
      {isFetching ? (
        <div className="mt-5">Loading data ...</div>
      ) : (
        <div>
          {status === 'success' && (
            <div>
              {/* {result?.map((inner: any, index: number) => {
                return <li key={index}>{inner.title}</li>;
              })} */}
               <p><strong>id:</strong> {result?.id}</p>
              <p>{result?.title}</p>
            </div>
          )}
        </div>
      )}
    </div>
  );
};

const queryClient = new QueryClient();

render(
  <QueryClientProvider client={queryClient}>
    <App />
  </QueryClientProvider>,
  document.getElementById('root')
);

标签: javascriptreactjsreact-query

解决方案


我在这里看到了多种误解:

  1. arefetch不会“清除”状态。事实上,react-query 永远不会仅仅因为你重新获取它就从活动查询中删除状态。这就是构建该库的整个 stale-while-revalidate 原则:在获取新数据时显示旧数据,然后在新数据进入时更新屏幕。这正是您的示例中发生的情况。

  2. 根本原因实际上是完全不同的:您使用相同的缓存键,然后强制调用refetch效果。这意味着

a)第一次获取将发生两次(一次来自 useQuery 调用,然后来自重新获取) b)你只会缓存最新的结果,这意味着你并没有真正使用从 react-query 到它的缓存。


最好的方法是将查询执行提取所需的所有依赖项放入查询键中。这也在此处的文档中

这样,react-query 将:

  • 当依赖关系发生变化时自动触发重新获取。
  • 如果在后台重新获取时有任何数据,请立即从缓存中为您提供数据。

将数据获取函数 ( ) 移出组件也是最佳实践,getData这样它就不会意外关闭属于查询键的内容。

它看起来像这样:

const App: React.FunctionComponent = () => {
  const [number, setNumber] = React.useState(1)

  const { data, status } = useQuery(['getData', number], () => getData(number));

就这样。没有效果,没有重取。

此外,您提供的一些选项是默认选项:staleTime默认为zerorefetchInterval默认情况下也是关闭的,因此您不必提供它。cacheTimeofzero仅当您想在使用查询后立即对其进行垃圾收集时才需要,这通常不是您想要的,尤其是因为键现在实际上正在更改,因为它们中有一个变量。

最后,您可能不想检查isFetching以卸载整个结果列表。isFetching每当进行提取时将始终为真,并且它不是状态机的一部分。使用更改键,您可能希望仅在 时显示微调器status === 'loading',因为当您第一次在数字之间切换时,您将获得这种硬加载状态。


推荐阅读