“react-query在调用setQueriesData后,不会重新获取缓存项的数据。”

huangapple go评论69阅读模式
英文:

react-query will not refetch data for cached item after `setQueriesData` is called

问题

我正在构建一个具有以下行为的搜索页面:

  1. 当页面加载时,使用默认的搜索参数执行查询。
  2. 当用户更新搜索参数时,使用新参数执行查询。
  3. 当用户“清除”搜索时,清除任何数据,但在他们输入新参数之前不要重新获取搜索结果。
  4. 当用户“重置”搜索时,使用默认的搜索参数执行查询。

为了处理情况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:

  1. when the page is loaded, execute a query with default search params
  2. when the user updates the search params, execute a query with the new params
  3. when the user clears the search, clear any data but do not re-fetch the search until they have entered new params
  4. 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(&#39;&#39;);
  useQuery({
     queryKey: [&#39;search&#39;, params],
     enabled: Boolean(params),
     queryFn: () =&gt; console.log(params, &#39;print&#39;),
  });

   return (
     &lt;div className={styles.container}&gt;
       &lt;input
         type=&quot;text&quot;
         value={params}
         onChange={(e) =&gt; setParams(e.target.value)}
       /&gt;
    &lt;/div&gt;
  );
 }

答案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: &#39;bar&#39;, cacheBuster: null};

const queryClient = useQueryClient();
const [params, setParams] = useState(defaultParams);
const {data, isLoading, isFetching} = useQuery({
  querykey: [&#39;search&#39;, params],
  queryFn: () =&gt; fetch(...),
});

const clearSearch = () =&gt; {
  queryClient.setQueriesData({queryKey: [&#39;search&#39;], exact: false}, []});
  setParams(defaultParams);
}

const resetSearch = () =&gt; setParams({...defaultParams, cacheBuster: Date.now()});

const submitSearch = (nextParams) =&gt; {
  // Date.now() ensures the params are always different, so the query automatically re-runs.
  setParams({...nextParams, cacheBuster: Date.now());
}

huangapple
  • 本文由 发表于 2023年6月1日 04:44:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76377145.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定