Add preliminary useEntityActions hook

develop^2
Alex Gleason 2023-03-14 14:24:11 -05:00
rodzic 8f8807eb76
commit ac76af41b2
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
5 zmienionych plików z 86 dodań i 4 usunięć

Wyświetl plik

@ -1,2 +1,3 @@
export { useEntities } from './useEntities';
export { useEntity } from './useEntity';
export { useEntity } from './useEntity';
export { useEntityActions } from './useEntityActions';

Wyświetl plik

@ -0,0 +1,6 @@
import type { Entity } from '../types';
import type z from 'zod';
type EntitySchema<TEntity extends Entity = Entity> = z.ZodType<TEntity, z.ZodTypeDef, any>;
export type { EntitySchema };

Wyświetl plik

@ -8,6 +8,7 @@ import { filteredArray } from 'soapbox/schemas/utils';
import { entitiesFetchFail, entitiesFetchRequest, entitiesFetchSuccess } from '../actions';
import type { Entity, EntityListState } from '../types';
import type { EntitySchema } from './types';
import type { RootState } from 'soapbox/store';
/** Tells us where to find/store the entity in the cache. */
@ -21,7 +22,7 @@ type EntityPath = [
/** Additional options for the hook. */
interface UseEntitiesOpts<TEntity extends Entity> {
/** A zod schema to parse the API entities. */
schema?: z.ZodType<TEntity, z.ZodTypeDef, any>
schema?: EntitySchema<TEntity>
/**
* Time (milliseconds) until this query becomes stale and should be refetched.
* It is 1 minute by default, and can be set to `Infinity` to opt-out of automatic fetching.

Wyświetl plik

@ -6,13 +6,14 @@ import { useApi, useAppDispatch, useAppSelector } from 'soapbox/hooks';
import { importEntities } from '../actions';
import type { Entity } from '../types';
import type { EntitySchema } from './types';
type EntityPath = [entityType: string, entityId: string]
/** Additional options for the hook. */
interface UseEntityOpts<TEntity> {
interface UseEntityOpts<TEntity extends Entity> {
/** A zod schema to parse the API entity. */
schema?: z.ZodType<TEntity, z.ZodTypeDef, any>
schema?: EntitySchema<TEntity>
/** Whether to refetch this entity every time the hook mounts, even if it's already in the store. */
refetch?: boolean
}

Wyświetl plik

@ -0,0 +1,73 @@
import { z } from 'zod';
import { useApi, useAppDispatch } from 'soapbox/hooks';
import { importEntities } from '../actions';
import type { Entity } from '../types';
import type { EntitySchema } from './types';
import type { AxiosResponse } from 'axios';
type EntityPath = [entityType: string, listKey?: string]
interface UseEntityActionsOpts<TEntity extends Entity = Entity> {
schema?: EntitySchema<TEntity>
}
interface CreateEntityResult<TEntity extends Entity = Entity> {
response: AxiosResponse
entity: TEntity
}
interface DeleteEntityResult {
response: AxiosResponse
}
interface EntityActionEndpoints {
post?: string
delete?: string
}
function useEntityActions<TEntity extends Entity = Entity, P = any>(
path: EntityPath,
endpoints: EntityActionEndpoints,
opts: UseEntityActionsOpts<TEntity> = {},
) {
const api = useApi();
const dispatch = useAppDispatch();
const [entityType, listKey] = path;
function createEntity(params: P): Promise<CreateEntityResult<TEntity>> {
if (!endpoints.post) return Promise.reject(endpoints);
return api.post(endpoints.post, params).then((response) => {
const schema = opts.schema || z.custom<TEntity>();
const entity = schema.parse(response.data);
// TODO: optimistic updating
dispatch(importEntities([entity], entityType, listKey));
return {
response,
entity,
};
});
}
function deleteEntity(entityId: string): Promise<DeleteEntityResult> {
if (!endpoints.delete) return Promise.reject(endpoints);
return api.delete(endpoints.delete.replaceAll(':id', entityId)).then((response) => {
return {
response,
};
});
}
return {
createEntity: endpoints.post ? createEntity : undefined,
deleteEntity: endpoints.delete ? deleteEntity : undefined,
};
}
export { useEntityActions };