通过数据哈希匹配防止 React-Query 中的数据刷新
Prevent data refresh in React-Query by data hash matching
我用 React-Query returns 命中的 API 一组数据和该数据的哈希键,格式如下:
{
orders:[{order1},{order2},....]
dataHash:number
}
我使用此 dataHash 检查 useQuery()
选项中的请求结果是否相等,以便 reach-query 可以轻松地自行比较大数据集,如下所示:
isDataEqual:(oldData, newData)=>oldData?.dataHash === newData.dataHash, //do not refresh page if hashes are equal
API 还有一项功能,如果 dataHash 与请求中的匹配,则允许不发送数据集。在这种情况下,它只有 returns 以下内容:
{
orders:[] //empty array here
dataHash:number
}
但由于我的比较函数只查看 dataHash,因此不会使用新数据,一切都会按预期工作。
我目前遇到的问题是,我似乎无法在 react-query 中找到一种内置方法来保存旧请求中的 dataHash,以便将其作为参数传递到新请求中。理想情况下,我希望看到 react-query 将旧数据传递到请求函数中,这样我就可以自己比较它,但这不是一个选项。
我还发现它将某种元数据对象传递到请求查询中,但我还没有找到针对任何特定请求改变此对象的方法。我错过了什么吗?
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() returns false 并用空结果更新数据。
我认为我需要能够保存每个请求的 dataHash(从未定义开始)但这意味着 queryFn 需要访问“oldData.data.dataHash”才能发送它。目前我没有看看如何做到这一点。
您 return 来自 queryFn
的任何内容都将被放入查询缓存中,因此可以作为来自 useQuery
data
return 的内容使用以及 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
.
中使用它
我用 React-Query returns 命中的 API 一组数据和该数据的哈希键,格式如下:
{
orders:[{order1},{order2},....]
dataHash:number
}
我使用此 dataHash 检查 useQuery()
选项中的请求结果是否相等,以便 reach-query 可以轻松地自行比较大数据集,如下所示:
isDataEqual:(oldData, newData)=>oldData?.dataHash === newData.dataHash, //do not refresh page if hashes are equal
API 还有一项功能,如果 dataHash 与请求中的匹配,则允许不发送数据集。在这种情况下,它只有 returns 以下内容:
{
orders:[] //empty array here
dataHash:number
}
但由于我的比较函数只查看 dataHash,因此不会使用新数据,一切都会按预期工作。
我目前遇到的问题是,我似乎无法在 react-query 中找到一种内置方法来保存旧请求中的 dataHash,以便将其作为参数传递到新请求中。理想情况下,我希望看到 react-query 将旧数据传递到请求函数中,这样我就可以自己比较它,但这不是一个选项。
我还发现它将某种元数据对象传递到请求查询中,但我还没有找到针对任何特定请求改变此对象的方法。我错过了什么吗?
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() returns false 并用空结果更新数据。
我认为我需要能够保存每个请求的 dataHash(从未定义开始)但这意味着 queryFn 需要访问“oldData.data.dataHash”才能发送它。目前我没有看看如何做到这一点。
您 return 来自 queryFn
的任何内容都将被放入查询缓存中,因此可以作为来自 useQuery
data
return 的内容使用以及 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
.