我使用React-Query调用的API以如下形式返回一组数据和该数据的哈希键:
{
orders:[{order1},{order2},....]
dataHash:number
}
我使用这个dataHash来检查useQuery()
选项内的请求结果是否相等,以使reach查询更容易在自己的数据集上比较大数据集,如下所示:
isDataEqual:(oldData, newData)=>oldData?.dataHash === newData.dataHash, //do not refresh page if hashes are equal
API还有一个功能,允许在dataHash与请求中的数据集匹配时不发送数据集。在这种情况下,它只返回以下内容:
{
orders:[] //empty array here
dataHash:number
}
但由于我的比较函数只查看dataHash,所以不会使用新数据,一切都会按预期进行。
我目前遇到的问题是,我似乎无法在react查询中找到一种内置的方法来保存旧请求中的dataHash,以便将其作为参数传递到新请求中。理想情况下,我希望看到react查询将旧数据传递到请求函数中,这样我就可以自己进行比较,但这不是一个选项。
我还发现它将某种元数据对象传递到请求查询中,但我还没有找到针对任何特定请求更改此对象的方法。我是不是错过了什么?
const getOrders = async (metadata:any): Promise<ShowOrdersResponse> => {
console.log(metadata) //this holds the "meta" object and query keys
const request: ShowOrdersRequest = {
searchParam: mySearchParam,
dataHash: 12//dataHash
};
const {data} = await secureAxios.post<ShowOrdersResponse>(ApiEndpoints.ShowOrders, request)
return data;
}
const {data} = useQuery<ShowWorkOrdersResponse>(['workorders', mySearchParam], getOrders, {
cacheTime: 30000,
refetchInterval: 5000,
isDataEqual:(oldData, newData)=>oldData?.dataHash === newData.dataHash, //do not refresh page if hashes are equal, this works as charm
meta:{dataHash:555} //I am able to pass this "meta" object into the request query, but cannot mutate it
});
第1版:我实施了建议的解决方案,但它仍然没有完全解决问题。目前,我正在将服务器返回的dataHash保存在组件状态中,如下所示:
onSuccess: (data) => setDataHash(data?.data.dataHash)
后来,我用不同的搜索参数调用useQuery((,它认为这是一个完全不同的请求,但由于我发送的是相同的哈希,所以没有得到任何结果。isDataEqual((返回false,并用空结果更新数据。
我认为我需要一种能力来保存每个请求的dataHash(从未定义开始(,但这意味着queryFn需要访问";oldData.data.dataHash";发送它。目前我不知道如何做到这一点。
从queryFn
返回的任何内容都将被放入查询缓存中,因此可以作为从useQuery
返回的data
以及在isDataEqual
函数上使用(因为传递的是相同的data
(。所以我会这么做:
const getOrders = async (): Promise<ShowOrdersResponse> => {
const request: ShowOrdersRequest = {
searchParam: mySearchParam,
dataHash: 12
};
const { data } = await secureAxios.post<ShowOrdersResponse>(ApiEndpoints.ShowOrders, request)
return {
data,
dataHash
}
}
useQuery(
['workorders', mySearchParam],
getOrders,
{
isDataEqual:(oldData, newData) => oldData?.dataHash === newData.dataHash,
}
)
当然,一个缺点是您需要在组件中打开data.data
,但您可以使用select
函数来解决这个问题:
useQuery(
['workorders', mySearchParam],
getOrders,
{
isDataEqual:(oldData, newData) => oldData?.dataHash === newData.dataHash,
select: data => data.data
}
)
这是因为isDataEqual
直接从缓存中传递数据,而每个组件(观察者(在运行select
后都会传递数据。所以基本上,您只需要传递dataHash
,这样您就可以在isDataEqual
中使用它。
我的解决方案是修改queryFn
,使其接收缓存的数据作为第二个可选参数,并在适当的时候返回。请参阅相关问题中的详细信息。