为重新获取设置状态对象时反应查询隐藏错误消息
React query hide error message when setting state object for refetching
在 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')
);
我在这里看到了多种误解:
a refetch
不会“清除”状态。事实上,react-query 永远不会因为你重新获取它而从活动查询中删除状态。这就是该库所建立的整个陈旧而重新验证的原则:在获取新数据时显示旧数据,然后在新数据进入后更新屏幕。这正是您的示例中发生的事情。
根本原因实际上完全不同:您使用相同的缓存键,然后在效果中强制调用 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
of zero
只有当你想在查询被使用后立即进行垃圾收集时才需要,这通常不是你想要的,特别是因为键现在实际上正在改变,因为它们中有一个变量.
最后,您可能不想检查 isFetching
以卸载整个结果列表。 isFetching
只要有取指操作,它就永远为真,它不是状态机的一部分。使用不断变化的键,您可能想要的是仅在 status === 'loading'
时显示微调器,因为当您第一次在数字之间切换时会遇到这种硬加载状态。
在 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')
);
我在这里看到了多种误解:
a
refetch
不会“清除”状态。事实上,react-query 永远不会因为你重新获取它而从活动查询中删除状态。这就是该库所建立的整个陈旧而重新验证的原则:在获取新数据时显示旧数据,然后在新数据进入后更新屏幕。这正是您的示例中发生的事情。根本原因实际上完全不同:您使用相同的缓存键,然后在效果中强制调用
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
of zero
只有当你想在查询被使用后立即进行垃圾收集时才需要,这通常不是你想要的,特别是因为键现在实际上正在改变,因为它们中有一个变量.
最后,您可能不想检查 isFetching
以卸载整个结果列表。 isFetching
只要有取指操作,它就永远为真,它不是状态机的一部分。使用不断变化的键,您可能想要的是仅在 status === 'loading'
时显示微调器,因为当您第一次在数字之间切换时会遇到这种硬加载状态。