diff --git a/app/soapbox/entity-store/hooks/useCreateEntity.ts b/app/soapbox/entity-store/hooks/useCreateEntity.ts index 432bea8fa..7df1220b1 100644 --- a/app/soapbox/entity-store/hooks/useCreateEntity.ts +++ b/app/soapbox/entity-store/hooks/useCreateEntity.ts @@ -13,7 +13,7 @@ interface UseCreateEntityOpts { schema?: EntitySchema } -interface EntityCallbacks { +interface CreateEntityCallbacks { onSuccess?(entity: TEntity): void onError?(error: Error): void } @@ -30,7 +30,7 @@ function useCreateEntity( return async function createEntity( data: Data, - callbacks: EntityCallbacks = {}, + callbacks: CreateEntityCallbacks = {}, ): Promise { try { const result = await api.request({ diff --git a/app/soapbox/entity-store/hooks/useDeleteEntity.ts b/app/soapbox/entity-store/hooks/useDeleteEntity.ts index 363dcf8a9..790a6dba8 100644 --- a/app/soapbox/entity-store/hooks/useDeleteEntity.ts +++ b/app/soapbox/entity-store/hooks/useDeleteEntity.ts @@ -1,11 +1,14 @@ -import { useAppDispatch, useGetState } from 'soapbox/hooks'; +import { useApi, useAppDispatch, useGetState } from 'soapbox/hooks'; import { deleteEntities, importEntities } from '../actions'; -type DeleteFn = (entityId: string) => Promise | 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( +function useDeleteEntity( entityType: string, - deleteFn: DeleteFn, + request: EntityRequest, ) { + const api = useApi(); const dispatch = useAppDispatch(); const getState = useGetState(); - return async function deleteEntity(entityId: string, callbacks: EntityCallbacks = {}): Promise { + return async function deleteEntity(entityId: string, callbacks: DeleteEntityCallbacks = {}): Promise { // 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( 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(); + } } }; } diff --git a/app/soapbox/entity-store/hooks/useEntityActions.ts b/app/soapbox/entity-store/hooks/useEntityActions.ts index 509e3c95e..63ede41d5 100644 --- a/app/soapbox/entity-store/hooks/useEntityActions.ts +++ b/app/soapbox/entity-store/hooks/useEntityActions.ts @@ -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( endpoints: EntityActionEndpoints, opts: UseEntityActionsOpts = {}, ) { - const api = useApi(); const { entityType, path } = parseEntitiesPath(expandedPath); - const [isLoading, setIsLoading] = useState(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(path, { method: 'post', url: endpoints.post }, opts); const createEntity: typeof create = async (...args) => { @@ -41,6 +32,11 @@ function useEntityActions( setIsLoading(false); }; + const deleteEntity: typeof _delete = async (...args) => { + await _delete(...args); + setIsLoading(false); + }; + return { createEntity, deleteEntity,