EntityStore: allow passing an undefined endpoint (to skip fetch), prevent race conditions in isFetching
This commit is contained in:
parent
a3b1f541bc
commit
ad583c89f8
1 changed files with 10 additions and 3 deletions
|
@ -6,6 +6,7 @@ import { useApi, useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||||
import { entitiesFetchFail, entitiesFetchRequest, entitiesFetchSuccess } from '../actions';
|
import { entitiesFetchFail, entitiesFetchRequest, entitiesFetchSuccess } from '../actions';
|
||||||
|
|
||||||
import type { Entity } from '../types';
|
import type { Entity } from '../types';
|
||||||
|
import type { RootState } from 'soapbox/store';
|
||||||
|
|
||||||
/** Tells us where to find/store the entity in the cache. */
|
/** Tells us where to find/store the entity in the cache. */
|
||||||
type EntityPath = [
|
type EntityPath = [
|
||||||
|
@ -30,8 +31,8 @@ interface UseEntitiesOpts<TEntity> {
|
||||||
function useEntities<TEntity extends Entity>(
|
function useEntities<TEntity extends Entity>(
|
||||||
/** Tells us where to find/store the entity in the cache. */
|
/** Tells us where to find/store the entity in the cache. */
|
||||||
path: EntityPath,
|
path: EntityPath,
|
||||||
/** API route to GET, eg `'/api/v1/notifications'` */
|
/** API route to GET, eg `'/api/v1/notifications'`. If undefined, nothing will be fetched. */
|
||||||
endpoint: string,
|
endpoint: string | undefined,
|
||||||
/** Additional options for the hook. */
|
/** Additional options for the hook. */
|
||||||
opts: UseEntitiesOpts<TEntity> = {},
|
opts: UseEntitiesOpts<TEntity> = {},
|
||||||
) {
|
) {
|
||||||
|
@ -64,6 +65,10 @@ function useEntities<TEntity extends Entity>(
|
||||||
const hasPreviousPage = Boolean(list?.state.prev);
|
const hasPreviousPage = Boolean(list?.state.prev);
|
||||||
|
|
||||||
const fetchPage = async(url: string): Promise<void> => {
|
const fetchPage = async(url: string): Promise<void> => {
|
||||||
|
// 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));
|
dispatch(entitiesFetchRequest(entityType, listKey));
|
||||||
try {
|
try {
|
||||||
const response = await api.get(url);
|
const response = await api.get(url);
|
||||||
|
@ -80,7 +85,9 @@ function useEntities<TEntity extends Entity>(
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchEntities = async(): Promise<void> => {
|
const fetchEntities = async(): Promise<void> => {
|
||||||
await fetchPage(endpoint);
|
if (endpoint) {
|
||||||
|
await fetchPage(endpoint);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchNextPage = async(): Promise<void> => {
|
const fetchNextPage = async(): Promise<void> => {
|
||||||
|
|
Loading…
Reference in a new issue