英文:
react-query will not refetch data for cached item after `setQueriesData` is called
问题
我正在构建一个具有以下行为的搜索页面:
- 当页面加载时,使用默认的搜索参数执行查询。
- 当用户更新搜索参数时,使用新参数执行查询。
- 当用户“清除”搜索时,清除任何数据,但在他们输入新参数之前不要重新获取搜索结果。
- 当用户“重置”搜索时,使用默认的搜索参数执行查询。
为了处理情况3,我正在手动设置查询的数据,因为我找不到一种方法可以在不重新获取的情况下清除数据。这导致了一个bug;如果用户更新搜索参数,然后清除搜索,然后再次使用先前的搜索参数,查询不会重新获取,并且手动设置的“清除”数据仍然存在。
我应该使用什么模式/方法来强制重新获取,即使查询键已经存在于缓存中?我已经尝试在我的“清除”调用中使用invalidateQueries
,但这会导致查询重新获取,这不是期望的行为。
const queryClient = useQueryClient();
const [params, setParams] = useState(defaultParams);
const {data, isLoading, isFetching} = useQuery({
queryKey: ['search', params],
queryFn: () => fetch(...),
});
const clearSearch = () => {
queryClient.setQueryData(['search'], []); // 修改此行以清除数据
}
const resetSearch = () => setParams(defaultParams);
const submitSearch = (nextParams) => {
// 如果使用参数 A 调用此函数,然后调用 clearSearch,
// 然后再次使用参数 A 调用此函数,查询将不会重新获取
setParams(nextParams);
}
英文:
I'm building a search page with the following behavior:
- when the page is loaded, execute a query with default search params
- when the user updates the search params, execute a query with the new params
- when the user
clears
the search, clear any data but do not re-fetch the search until they have entered new params - when the user
resets
the search, execute a query with the default search params.
To handle case 3
, I am manually setting the data of the query, because I can't find a method that will allow me to clear the data without re-fetching. This is causing a bug; if the user updates the search params, then clears the search, then uses the previous search params again, the query does not re-fetch, and the manually set "cleared" data persists.
What pattern/method should I be using to force the refetch, even if the query key already exists in the cache? I have tried using invalidateQueries
in my clear
call, but that causes the query to re-fetch, which is not the desired behavior.
const queryClient = useQueryClient();
const [params, setParams] = useState(defaultParams);
const {data, isLoading, isFetching} = useQuery({
querykey: ['search', params],
queryFn: () => fetch(...),
});
const clearSearch = () => {
queryClient.setQueriesData({queryKey: ['search'], exact: false}, []});
}
const resetSearch = () => setParams(defaultParams);
const submitSearch = (nextParams) => {
// if this is called with params = A, and then clearSearch is called,
// and this is called again with params = A, the query does not re-fetch
setParams(nextParams);
}
答案1
得分: 0
你应该使用useEffect
钩子来在params发生变化时重新获取数据。
useEffect(() => {
// 重新获取数据
}, [params]);
英文:
you should use the useEffect
hook to refetch everytime the params changes
useEffect(() => {
// refetch
}, [params])
答案2
得分: 0
你可以通过使用useQuery Hook中的enabled属性来实现你的结果。
通过检查param状态是否不是有效的字符串,你可以在运行时启用或禁用useQuery。
例如:
export default function Dummy() {
const [params, setParams] = React.useState('');
useQuery({
queryKey: ['search', params],
enabled: Boolean(params),
queryFn: () => console.log(params, 'print'),
});
return (
<div className={styles.container}>
<input
type="text"
value={params}
onChange={(e) => setParams(e.target.value)}
/>
</div>
);
}
英文:
You can accomplish your result by using the the enabled property in useQuery Hook.
By checking if the param state is not a valid string, you can enable or disable on runtime the useQuery.
As example:
export default function Dummy() {
const [params, setParams] = React.useState('');
useQuery({
queryKey: ['search', params],
enabled: Boolean(params),
queryFn: () => console.log(params, 'print'),
});
return (
<div className={styles.container}>
<input
type="text"
value={params}
onChange={(e) => setParams(e.target.value)}
/>
</div>
);
}
答案3
得分: 0
在与同事协商后,我最终将一个名为 cacheBuster
的参数添加到我的载荷中,将其赋值为 Date.now() | null
;
const defaultParams = {foo: 'bar', cacheBuster: null};
const queryClient = useQueryClient();
const [params, setParams] = useState(defaultParams);
const {data, isLoading, isFetching} = useQuery({
querykey: ['search', params],
queryFn: () => fetch(...),
});
const clearSearch = () => {
queryClient.setQueriesData({queryKey: ['search'], exact: false}, []);
setParams(defaultParams);
}
const resetSearch = () => setParams({...defaultParams, cacheBuster: Date.now()});
const submitSearch = (nextParams) => {
// Date.now() 确保参数始终不同,因此查询会自动重新运行。
setParams({...nextParams, cacheBuster: Date.now()});
}
英文:
After consulting with a colleague, I ended up putting a cacheBuster
parameter into my payload, which I assigned to Date.now() | null
;
const defaultParams = {foo: 'bar', cacheBuster: null};
const queryClient = useQueryClient();
const [params, setParams] = useState(defaultParams);
const {data, isLoading, isFetching} = useQuery({
querykey: ['search', params],
queryFn: () => fetch(...),
});
const clearSearch = () => {
queryClient.setQueriesData({queryKey: ['search'], exact: false}, []});
setParams(defaultParams);
}
const resetSearch = () => setParams({...defaultParams, cacheBuster: Date.now()});
const submitSearch = (nextParams) => {
// Date.now() ensures the params are always different, so the query automatically re-runs.
setParams({...nextParams, cacheBuster: Date.now());
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论