reactjs 使用useQueryClient挂接在React中有条件地使缓存的查询无效

xienkqul  于 2022-12-22  发布在  React
关注(0)|答案(1)|浏览(179)

我是一个很新的React,并与数据提取/重新提取的一个微妙的问题斗争。
我们有一个带有自己UI的数据源,您可以通过该数据源创建多个讨论主题,并且该数据源对用户开放。这些主题可以通过UI中的注解和其他活动(删除注解/附件/链接)等进行更新。此数据源还公开列出系统中当前所有主题的终结点以及每个终结点上的用户活动的详细信息。
我们的用户界面是一个React应用程序,可与这些端点对话,并且:
1.列出了主题。
1.在点击其中一个项目时显示该项目的活动计数.(在一个单独的面板中有两个选项卡-一个用于注解,一个用于其他用户活动)
我对上面的第二点负责。
我编写了一个自定义钩子来实现这个目标,这个钩子由面板调用,并使用useQueryClient使我在钩子内的查询无效,但不幸的是,每次组件(panel)重新呈现或在选项卡之间切换时,会进行一个新的调用来获取计数,这被认为是不必要的。相反,我们希望获取计数的调用仅在用户单击项并打开面板时发出。但我无法在不违反钩子规则的情况下实现这一点(在条件内调用它/在react组件外调用它)。

export const useTopicActivityCounts = (
  topicId: string | undefined,
): ITopicActivityCounts | undefined => {
useQueryClient().invalidateQueries(['TopicActivitytCounts', { topicId }]);
const { data } = useQuery(
    ['TopicActivityCounts', { topicId }],
    () =>
      fetchAsync<IResult<ITopicActivityCount>>(endpointUrl, {
        method: 'GET',
        params: {
          id,
        },
      }).then(resp => resp?.value),
    {
      enabled: !!topicId,
      staleTime: Infinity,
    },
  );
  return data;

这个钩子从这里被调用:

export const TopicDetails = memo(({ item, setItem }: ITopicDetails): JSX.Element => {
  const counts = useTopicActivityCounts(item?.id);

  const headerContent = (
    <Stack>
      /* page content */
    </Stack>
  );

  const items = [
    /* page content */,
  ];

  const pivotItems = [
    {
      itemKey: 'Tab1',
      headerText: localize('Resx.Comms', { count: counts?.commentsCount ?? '0' }),
    },
    {
      itemKey: 'Tab2',
      headerText: localize('Resx.Activities', { count: counts?.activitiesCount ?? '0' }),
    },
  ];

  return (
    /*
       page content
    */
  );
});

我试过把它放在钩子里面的一个onSuccess里面,但是没有成功。

92dk7w1h

92dk7w1h1#

看起来你在尝试防止钩子在组件重新呈现或者用户在标签页之间切换时被不必要地多次调用。你可以尝试的一种方法是将钩子 Package 在useCallback钩子中,并将topicId作为依赖项传递。这将确保钩子只在topicId改变时被调用。下面是一个如何做到这一点的示例:

const useTopicActivityCounts = useCallback((topicId: string | undefined) => {
  useQueryClient().invalidateQueries(['TopicActivitytCounts', { topicId }]);
  const { data } = useQuery(
    ['TopicActivityCounts', { topicId }],
    () =>
      fetchAsync<IResult<ITopicActivityCount>>(endpointUrl, {
        method: 'GET',
        params: {
          id,
        },
      }).then(resp => resp?.value),
    {
      enabled: !!topicId,
      staleTime: Infinity,
    },
  );
  return data;
}, [topicId]);

这样,useTopicActivityCounts钩子只会在topicId改变时被调用,你可以像以前一样使用这个钩子,但是现在它只会在topicId改变时被调用:

export const TopicDetails = memo(({ item, setItem }: ITopicDetails): JSX.Element => {
const counts = useTopicActivityCounts(item?.id);
// rest of the code

相关问题