【问题标题】:React query hide error message when setting state object for refetching设置状态对象以重新获取时反应查询隐藏错误消息
【发布时间】:2021-11-09 17:42:47
【问题描述】:

目前在 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')
);

【问题讨论】:

    标签: javascript reactjs react-query


    【解决方案1】:

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

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

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

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


    最好的方法是将您的查询执行获取所需的所有依赖项放入查询键。这也是in the docs here。

    这样,react-query 将:

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

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

    看起来像这样:

    const App: React.FunctionComponent = () => {
      const [number, setNumber] = React.useState(1)
    
      const { data, status } = useQuery(['getData', number], () => getData(number));
    
    

    就是这样。没有效果,没有重新获取。

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

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

    【讨论】:

    • 感谢您的澄清,帮助很大!
    猜你喜欢
    • 2012-06-09
    • 2019-03-19
    • 1970-01-01
    • 2020-08-10
    • 1970-01-01
    • 2023-03-21
    • 2011-03-20
    • 1970-01-01
    • 2014-01-28
    相关资源
    最近更新 更多