EntityStore: allow passing an EntityRequest object to useEntities
This commit is contained in:
parent
948d66bcab
commit
ad3f8acbe5
|
@ -15,6 +15,7 @@ import { getAccessToken, getAppToken, isURL, parseBaseURL } from 'soapbox/utils/
|
|||
|
||||
import type MockAdapter from 'axios-mock-adapter';
|
||||
|
||||
|
||||
/**
|
||||
Parse Link headers, mostly for pagination.
|
||||
@see {@link https://www.npmjs.com/package/http-link-header}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type { Entity } from '../types';
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
import type z from 'zod';
|
||||
|
||||
type EntitySchema<TEntity extends Entity = Entity> = z.ZodType<TEntity, z.ZodTypeDef, any>;
|
||||
|
@ -24,9 +25,16 @@ type EntitiesPath = [entityType: string, listKey: string]
|
|||
/** Used to look up a single entity by its ID. */
|
||||
type EntityPath = [entityType: string, entityId: string]
|
||||
|
||||
/**
|
||||
* Passed into hooks to make requests.
|
||||
* Can be a URL for GET requests, or a request object.
|
||||
*/
|
||||
type EntityRequest = string | URL | AxiosRequestConfig;
|
||||
|
||||
export type {
|
||||
EntitySchema,
|
||||
ExpandedEntitiesPath,
|
||||
EntitiesPath,
|
||||
EntityPath,
|
||||
EntityRequest,
|
||||
};
|
|
@ -8,10 +8,10 @@ import { realNumberSchema } from 'soapbox/utils/numbers';
|
|||
|
||||
import { entitiesFetchFail, entitiesFetchRequest, entitiesFetchSuccess, invalidateEntityList } from '../actions';
|
||||
|
||||
import { parseEntitiesPath } from './utils';
|
||||
import { parseEntitiesPath, toAxiosRequest } from './utils';
|
||||
|
||||
import type { Entity, EntityListState } from '../types';
|
||||
import type { EntitiesPath, EntitySchema, ExpandedEntitiesPath } from './types';
|
||||
import type { EntitiesPath, EntityRequest, EntitySchema, ExpandedEntitiesPath } from './types';
|
||||
import type { RootState } from 'soapbox/store';
|
||||
|
||||
/** Additional options for the hook. */
|
||||
|
@ -32,7 +32,7 @@ function useEntities<TEntity extends Entity>(
|
|||
/** Tells us where to find/store the entity in the cache. */
|
||||
expandedPath: ExpandedEntitiesPath,
|
||||
/** API route to GET, eg `'/api/v1/notifications'`. If undefined, nothing will be fetched. */
|
||||
endpoint: string | undefined,
|
||||
request: EntityRequest,
|
||||
/** Additional options for the hook. */
|
||||
opts: UseEntitiesOpts<TEntity> = {},
|
||||
) {
|
||||
|
@ -54,14 +54,14 @@ function useEntities<TEntity extends Entity>(
|
|||
const next = useListState(path, 'next');
|
||||
const prev = useListState(path, 'prev');
|
||||
|
||||
const fetchPage = async(url: string, overwrite = false): Promise<void> => {
|
||||
const fetchPage = async(req: EntityRequest, overwrite = false): Promise<void> => {
|
||||
// Get `isFetching` state from the store again to prevent race conditions.
|
||||
const isFetching = selectListState(getState(), path, 'fetching');
|
||||
if (isFetching) return;
|
||||
|
||||
dispatch(entitiesFetchRequest(entityType, listKey));
|
||||
try {
|
||||
const response = await api.get(url);
|
||||
const response = await api.request(toAxiosRequest(req));
|
||||
const schema = opts.schema || z.custom<TEntity>();
|
||||
const entities = filteredArray(schema).parse(response.data);
|
||||
const parsedCount = realNumberSchema.safeParse(response.headers['x-total-count']);
|
||||
|
@ -82,9 +82,7 @@ function useEntities<TEntity extends Entity>(
|
|||
};
|
||||
|
||||
const fetchEntities = async(): Promise<void> => {
|
||||
if (endpoint) {
|
||||
await fetchPage(endpoint, true);
|
||||
}
|
||||
await fetchPage(request, true);
|
||||
};
|
||||
|
||||
const fetchNextPage = async(): Promise<void> => {
|
||||
|
@ -114,7 +112,7 @@ function useEntities<TEntity extends Entity>(
|
|||
if (isInvalid || isUnset || isStale) {
|
||||
fetchEntities();
|
||||
}
|
||||
}, [endpoint, isEnabled]);
|
||||
}, [request, isEnabled]);
|
||||
|
||||
return {
|
||||
entities,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type { EntitiesPath, ExpandedEntitiesPath } from './types';
|
||||
import type { EntitiesPath, EntityRequest, ExpandedEntitiesPath } from './types';
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
|
||||
function parseEntitiesPath(expandedPath: ExpandedEntitiesPath) {
|
||||
const [entityType, ...listKeys] = expandedPath;
|
||||
|
@ -12,4 +13,15 @@ function parseEntitiesPath(expandedPath: ExpandedEntitiesPath) {
|
|||
};
|
||||
}
|
||||
|
||||
export { parseEntitiesPath };
|
||||
function toAxiosRequest(req: EntityRequest): AxiosRequestConfig {
|
||||
if (typeof req === 'string' || req instanceof URL) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: req.toString(),
|
||||
};
|
||||
}
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
export { parseEntitiesPath, toAxiosRequest };
|
|
@ -52,11 +52,10 @@ function useGroupRelationship(groupId: string) {
|
|||
|
||||
function useGroupRelationships(groupIds: string[]) {
|
||||
const q = groupIds.map(id => `id[]=${id}`).join('&');
|
||||
const endpoint = groupIds.length ? `/api/v1/groups/relationships?${q}` : undefined;
|
||||
const { entities, ...result } = useEntities<GroupRelationship>(
|
||||
[Entities.GROUP_RELATIONSHIPS, ...groupIds],
|
||||
endpoint,
|
||||
{ schema: groupRelationshipSchema },
|
||||
`/api/v1/groups/relationships?${q}`,
|
||||
{ schema: groupRelationshipSchema, enabled: groupIds.length > 0 },
|
||||
);
|
||||
|
||||
const relationships = entities.reduce<Record<string, GroupRelationship>>((map, relationship) => {
|
||||
|
|
Loading…
Reference in New Issue