diff --git a/app/soapbox/entity-store/hooks/useEntities.ts b/app/soapbox/entity-store/hooks/useEntities.ts index ee64d6437..909273ea3 100644 --- a/app/soapbox/entity-store/hooks/useEntities.ts +++ b/app/soapbox/entity-store/hooks/useEntities.ts @@ -6,6 +6,7 @@ import { useApi, useAppDispatch, useAppSelector } from 'soapbox/hooks'; import { entitiesFetchFail, entitiesFetchRequest, entitiesFetchSuccess } from '../actions'; import type { Entity } from '../types'; +import type { RootState } from 'soapbox/store'; /** Tells us where to find/store the entity in the cache. */ type EntityPath = [ @@ -30,8 +31,8 @@ interface UseEntitiesOpts { function useEntities( /** Tells us where to find/store the entity in the cache. */ path: EntityPath, - /** API route to GET, eg `'/api/v1/notifications'` */ - endpoint: string, + /** API route to GET, eg `'/api/v1/notifications'`. If undefined, nothing will be fetched. */ + endpoint: string | undefined, /** Additional options for the hook. */ opts: UseEntitiesOpts = {}, ) { @@ -64,6 +65,10 @@ function useEntities( const hasPreviousPage = Boolean(list?.state.prev); const fetchPage = async(url: string): Promise => { + // Get `isFetching` state from the store again to prevent race conditions. + const isFetching = dispatch((_, getState: () => RootState) => Boolean(getState().entities[entityType]?.lists[listKey]?.state.fetching)); + if (isFetching) return; + dispatch(entitiesFetchRequest(entityType, listKey)); try { const response = await api.get(url); @@ -80,7 +85,9 @@ function useEntities( }; const fetchEntities = async(): Promise => { - await fetchPage(endpoint); + if (endpoint) { + await fetchPage(endpoint); + } }; const fetchNextPage = async(): Promise => {