diff --git a/ui/src/logic/useReactQuerySubscription.tsx b/ui/src/logic/useReactQuerySubscription.tsx index 0b75c21362..be0a2dd3a0 100644 --- a/ui/src/logic/useReactQuerySubscription.tsx +++ b/ui/src/logic/useReactQuerySubscription.tsx @@ -16,6 +16,7 @@ export default function useReactQuerySubscription({ scry, scryApp = app, priority = 3, + onEvent, options, }: { queryKey: QueryKey; @@ -24,6 +25,7 @@ export default function useReactQuerySubscription({ scry: string; scryApp?: string; priority?: number; + onEvent?: (data: Event) => void; options?: UseQueryOptions; }) { const queryClient = useQueryClient(); @@ -50,9 +52,9 @@ export default function useReactQuerySubscription({ api.subscribe({ app, path, - event: invalidate.current, + event: onEvent ? onEvent : invalidate.current, }); - }, [app, path, queryClient, queryKey]); + }, [app, path, queryClient, queryKey, onEvent]); return useQuery(queryKey, fetchData, { staleTime: 60 * 1000, diff --git a/ui/src/state/groups/groups.ts b/ui/src/state/groups/groups.ts index 958eaa23b2..37ecb8c7db 100644 --- a/ui/src/state/groups/groups.ts +++ b/ui/src/state/groups/groups.ts @@ -1,6 +1,6 @@ import _ from 'lodash'; import { useParams } from 'react-router'; -import { useCallback, useEffect, useMemo } from 'react'; +import { useCallback, useEffect, useMemo, useRef } from 'react'; import create from 'zustand'; import { MutationFunction, @@ -248,18 +248,41 @@ const defGang = { export function useGangs() { const queryClient = useQueryClient(); + const queryKey = ['gangs']; + + const invalidate = useRef( + _.debounce( + () => { + queryClient.invalidateQueries(queryKey); + }, + 300, + { leading: true, trailing: true } + ) + ); + const { data, ...rest } = useReactQuerySubscription({ - queryKey: ['gangs'], + queryKey, app: 'groups', path: `/gangs/updates`, scry: `/gangs`, + onEvent: (event) => { + // right now for long group joins, the gang is initially removed but no fact about the corresponding created + // group is emitted until the join completes. This is a blunt hack to ensure our view of existing groups remains up to date. + // Once this is fixed, we should remove this and use the default useReactQuerySubscription event handler + const currGangCount = Object.keys( + queryClient.getQueryData(queryKey) || {} + ).length; + const newGangCount = Object.keys(event || {}).length; + const gangWasRemoved = + currGangCount && newGangCount && newGangCount < currGangCount; + if (gangWasRemoved) { + queryClient.invalidateQueries(['groups']); + } + + invalidate.current(); + }, options: { refetchOnMount: false, - onSuccess: () => { - // TEMPORARY: right now for long group joins, the gang is initially removed but no fact about the corresponding created - // group is emitted until the join completes. This is a blunt hack to ensure our view of existing groups remains up to date - queryClient.invalidateQueries(['groups']); - }, }, });