【问题标题】:React Query: rerun onSuccess method of a cached queryReact Query:重新运行缓存查询的 onSuccess 方法
【发布时间】:2022-12-15 11:11:10
【问题描述】:

我有的

我正在获取我用来调用 google geocode API 的用户位置(纬度/经度),除非用户的坐标发生变化,否则请求不会再次运行,因为查询使用用户的坐标作为 queryKey 数组依赖项。

问题

问题是我在 onSuccess 查询方法中运行一些操作,此方法仅在任何 queryKey 依赖项更改时运行,我提到这不会发生。

无论queryKey依赖关系是否改变,如何运行onSuccess方法?

参考代码

export const useGoogleReverseGeocoding = (coords) => {
  const url = 'someUrl';
  const request = createClient(); // axios abstraction

  return useQuery({
    queryKey: ['google-geocode', coords],
    queryFn: request,
    enabled: !!coords,
    onSuccess: (data) => {
      const searchTerm = removeGlobalCodeText(data?.plus_code?.compound_code);
      // set searchterm in a global store. This searchterm change with 
      // different user actions, so if the user re-share his location
      // I need to run onSuccess transformation again.
      setSearchTerm(searchTerm); 
    },
  });
};

【问题讨论】:

  • 如果你想重新运行 use Query,它返回 refetch 并且我认为传递给钩子的坐标是一个对象,你可以解构它以防止额外的重新渲染
  • 这是一种方法...我认为不推荐,因为它会再次运行查询(极有可能)...当您提供坐标以使用地理编码功能时,将其提供为 useGeocoding({ ...coords })
  • 您能否详细说明如何使用展开运算符来避免重新呈现或运行新的查询执行。另一方面,我不希望查询仅重新运行 onsuccess 代码。您是否认为最好使用一种效果来验证查询是否返回数据并在那里执行 onsuccess 代码?这个想法是利用反应查询缓存,但如果反应查询挂钩有数据,则运行 onsuccess 代码
  • 你需要详细说明。如果数据没有改变,为什么你需要“重新运行”你对数据的操作?你的 onSuccess 处理程序在做什么?我怀疑您正在以错误的方式解决这个问题,但我对用例的了解还不够多,无法为您提供建议。
  • 我所做的是转换来自 google places 的数据,并使用它以人类可读的方式显示用户当前位置的名称。我的意思是,如果用户像{coords: lat: 33.748997, lng: -84.387985} 那样分享他的位置,我将显示Atlanta,这是在 onSuccess 方法中运行的,但只执行一次,如果查询数据没有改变,则不会再次进行转换,我必须让明确此数据会随着某些用户操作而变化,因此如果用户再次共享他的位置,则必须重新运行转换。更新参考代码

标签: reactjs react-native react-query


【解决方案1】:

正如我在评论中解释的那样,onSuccess 不能在查询本身再次触发的情况下被触发。由于某些用户操作应该触发 onSuccess 上的转换,您有几种方法可以解决这个问题,其中之一是将这些转换移动到 useEffect 挂钩上,并在 dependencies 数组上添加一些与用户操作相关的标志.另一个建议的解决方案是根据这些用户操作将 invalidate the query 重新获取,并执行 onSuccess 上的转换。

您可以使用返回当前 QueryClient 实例的 useQueryClient 钩子来实现此目的。只要组件被 QueryClientProvider 包装,您就可以从任何地方使查询无效。对于此示例并为方便起见,我将在 useGoogleReverseGeocoding 自定义挂钩上包含此挂钩。

例子:

自定义挂钩:

export const useGoogleReverseGeocoding = (coords) => {
  const queryClient = useQueryClient()
  const url = 'someUrl';
  const request = createClient(); // axios abstraction

  const geocodingData = useQuery({
    queryKey: ['google-geocode', coords],
    queryFn: request,
    enabled: !!coords,
    onSuccess: (data) => {
      const searchTerm = removeGlobalCodeText(data?.plus_code?.compound_code);
      // set searchterm in a global store. This searchterm change with 
      // different user actions, so if the user re-share his location
      // I need to run onSuccess transformation again.
      setSearchTerm(searchTerm); 
    },
  });
  
  const invalidateQueryOnAction = () => queryClient.invalidateQueries(['google-geocode'])
  
  return { geocodingData, invalidateQueryOnAction }
};

一些组件:

const dummyCoords = {
    lat: 33.748997,
    lng: -84.387985
}

const SomeComponent = () => {
  const { geocodingData, invalidateQueryOnAction } =
    useGoogleReverseGeocoding(dummyCoords)

  const handleSomeUserAction = () => {
    // handle action...

    // Invalidate query, so the query gets refetched and onSuccess callback executes again
    invalidateQueryOnAction()
  }
}

PS:如果@TkDodo为此提供了不同的解决方案,我建议改为使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 2023-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多