useDeleteEntity: refactor with EntityRequest
This commit is contained in:
parent
50f65bc7c9
commit
1c5a6d8b41
|
@ -13,7 +13,7 @@ interface UseCreateEntityOpts<TEntity extends Entity = Entity> {
|
|||
schema?: EntitySchema<TEntity>
|
||||
}
|
||||
|
||||
interface EntityCallbacks<TEntity extends Entity = Entity, Error = unknown> {
|
||||
interface CreateEntityCallbacks<TEntity extends Entity = Entity, Error = unknown> {
|
||||
onSuccess?(entity: TEntity): void
|
||||
onError?(error: Error): void
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ function useCreateEntity<TEntity extends Entity = Entity, Data = any>(
|
|||
|
||||
return async function createEntity(
|
||||
data: Data,
|
||||
callbacks: EntityCallbacks = {},
|
||||
callbacks: CreateEntityCallbacks = {},
|
||||
): Promise<void> {
|
||||
try {
|
||||
const result = await api.request({
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
import { useAppDispatch, useGetState } from 'soapbox/hooks';
|
||||
import { useApi, useAppDispatch, useGetState } from 'soapbox/hooks';
|
||||
|
||||
import { deleteEntities, importEntities } from '../actions';
|
||||
|
||||
type DeleteFn<T> = (entityId: string) => Promise<T> | T;
|
||||
import { toAxiosRequest } from './utils';
|
||||
|
||||
interface EntityCallbacks {
|
||||
import type { EntityRequest } from './types';
|
||||
|
||||
interface DeleteEntityCallbacks {
|
||||
onSuccess?(): void
|
||||
onError?(): void
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -13,14 +16,15 @@ interface EntityCallbacks {
|
|||
* This hook should be used to globally delete an entity from all lists.
|
||||
* To remove an entity from a single list, see `useDismissEntity`.
|
||||
*/
|
||||
function useDeleteEntity<T = unknown>(
|
||||
function useDeleteEntity(
|
||||
entityType: string,
|
||||
deleteFn: DeleteFn<T>,
|
||||
request: EntityRequest,
|
||||
) {
|
||||
const api = useApi();
|
||||
const dispatch = useAppDispatch();
|
||||
const getState = useGetState();
|
||||
|
||||
return async function deleteEntity(entityId: string, callbacks: EntityCallbacks = {}): Promise<T> {
|
||||
return async function deleteEntity(entityId: string, callbacks: DeleteEntityCallbacks = {}): Promise<void> {
|
||||
// Get the entity before deleting, so we can reverse the action if the API request fails.
|
||||
const entity = getState().entities[entityType]?.store[entityId];
|
||||
|
||||
|
@ -28,21 +32,27 @@ function useDeleteEntity<T = unknown>(
|
|||
dispatch(deleteEntities([entityId], entityType, { preserveLists: true }));
|
||||
|
||||
try {
|
||||
const result = await deleteFn(entityId);
|
||||
// HACK: replace occurrences of `:id` in the URL. Maybe there's a better way?
|
||||
const axiosReq = toAxiosRequest(request);
|
||||
axiosReq.url?.replaceAll(':id', entityId);
|
||||
|
||||
await api.request(axiosReq);
|
||||
|
||||
// Success - finish deleting entity from the state.
|
||||
dispatch(deleteEntities([entityId], entityType));
|
||||
|
||||
if (callbacks.onSuccess) {
|
||||
callbacks.onSuccess();
|
||||
}
|
||||
|
||||
return result;
|
||||
} catch (e) {
|
||||
if (entity) {
|
||||
// If the API failed, reimport the entity.
|
||||
dispatch(importEntities([entity], entityType));
|
||||
}
|
||||
throw e;
|
||||
|
||||
if (callbacks.onError) {
|
||||
callbacks.onError();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
import { useState } from 'react';
|
||||
|
||||
import { useApi } from 'soapbox/hooks';
|
||||
|
||||
import { useCreateEntity } from './useCreateEntity';
|
||||
import { useDeleteEntity } from './useDeleteEntity';
|
||||
import { parseEntitiesPath } from './utils';
|
||||
|
@ -23,17 +21,10 @@ function useEntityActions<TEntity extends Entity = Entity, Data = any>(
|
|||
endpoints: EntityActionEndpoints,
|
||||
opts: UseEntityActionsOpts<TEntity> = {},
|
||||
) {
|
||||
const api = useApi();
|
||||
const { entityType, path } = parseEntitiesPath(expandedPath);
|
||||
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
|
||||
const deleteEntity = useDeleteEntity(entityType, (entityId) => {
|
||||
if (!endpoints.delete) return Promise.reject(endpoints);
|
||||
return api.delete(endpoints.delete.replace(':id', entityId))
|
||||
.finally(() => setIsLoading(false));
|
||||
});
|
||||
|
||||
const _delete = useDeleteEntity(entityType, { method: 'delete', url: endpoints.delete });
|
||||
const create = useCreateEntity<TEntity, Data>(path, { method: 'post', url: endpoints.post }, opts);
|
||||
|
||||
const createEntity: typeof create = async (...args) => {
|
||||
|
@ -41,6 +32,11 @@ function useEntityActions<TEntity extends Entity = Entity, Data = any>(
|
|||
setIsLoading(false);
|
||||
};
|
||||
|
||||
const deleteEntity: typeof _delete = async (...args) => {
|
||||
await _delete(...args);
|
||||
setIsLoading(false);
|
||||
};
|
||||
|
||||
return {
|
||||
createEntity,
|
||||
deleteEntity,
|
||||
|
|
Loading…
Reference in New Issue