From 4049de50aa0bd465881978eb624f13074f123024 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Wed, 22 Mar 2023 14:05:24 -0500 Subject: [PATCH] Add separate useDeleteEntity hook accepting a callback --- .../entity-store/hooks/useDeleteEntity.ts | 37 ++++++++++++++++ .../entity-store/hooks/useEntityActions.ts | 42 +++++-------------- 2 files changed, 48 insertions(+), 31 deletions(-) create mode 100644 app/soapbox/entity-store/hooks/useDeleteEntity.ts diff --git a/app/soapbox/entity-store/hooks/useDeleteEntity.ts b/app/soapbox/entity-store/hooks/useDeleteEntity.ts new file mode 100644 index 000000000..006912a9d --- /dev/null +++ b/app/soapbox/entity-store/hooks/useDeleteEntity.ts @@ -0,0 +1,37 @@ +import { useAppDispatch, useGetState } from 'soapbox/hooks'; + +import { deleteEntities, importEntities } from '../actions'; + +interface DeleteEntityResult { + result: T +} + +type DeleteFn = (entityId: string) => Promise | T; + +function useDeleteEntity(entityType: string, deleteFn: DeleteFn) { + const dispatch = useAppDispatch(); + const getState = useGetState(); + + return async function deleteEntity(entityId: string): Promise> { + // Get the entity before deleting, so we can reverse the action if the API request fails. + const entity = getState().entities[entityType]?.store[entityId]; + + // Optimistically delete the entity from the _store_ but keep the lists in tact. + dispatch(deleteEntities([entityId], entityType, { preserveLists: true })); + + try { + const result = await deleteFn(entityId); + // Success - finish deleting entity from the state. + dispatch(deleteEntities([entityId], entityType)); + return { result }; + } catch (e) { + if (entity) { + // If the API failed, reimport the entity. + dispatch(importEntities([entity], entityType)); + } + throw e; + } + }; +} + +export { useDeleteEntity }; \ No newline at end of file diff --git a/app/soapbox/entity-store/hooks/useEntityActions.ts b/app/soapbox/entity-store/hooks/useEntityActions.ts index eede5bcb3..8f286633a 100644 --- a/app/soapbox/entity-store/hooks/useEntityActions.ts +++ b/app/soapbox/entity-store/hooks/useEntityActions.ts @@ -1,8 +1,10 @@ import { z } from 'zod'; -import { useApi, useAppDispatch, useGetState } from 'soapbox/hooks'; +import { useApi, useAppDispatch } from 'soapbox/hooks'; -import { deleteEntities, importEntities } from '../actions'; +import { importEntities } from '../actions'; + +import { useDeleteEntity } from './useDeleteEntity'; import type { Entity } from '../types'; import type { EntitySchema } from './types'; @@ -19,10 +21,6 @@ interface CreateEntityResult { entity: TEntity } -interface DeleteEntityResult { - response: AxiosResponse -} - interface EntityActionEndpoints { post?: string delete?: string @@ -37,10 +35,15 @@ function useEntityActions( endpoints: EntityActionEndpoints, opts: UseEntityActionsOpts = {}, ) { + const [entityType, listKey] = path; + const api = useApi(); const dispatch = useAppDispatch(); - const getState = useGetState(); - const [entityType, listKey] = path; + + const deleteEntity = useDeleteEntity(entityType, (entityId) => { + if (!endpoints.delete) return Promise.reject(endpoints); + return api.delete(endpoints.delete.replace(':id', entityId)); + }); function createEntity(params: P, callbacks: EntityCallbacks = {}): Promise> { if (!endpoints.post) return Promise.reject(endpoints); @@ -63,29 +66,6 @@ function useEntityActions( }); } - function deleteEntity(entityId: string): Promise { - if (!endpoints.delete) return Promise.reject(endpoints); - // Get the entity before deleting, so we can reverse the action if the API request fails. - const entity = getState().entities[entityType]?.store[entityId]; - // Optimistically delete the entity from the _store_ but keep the lists in tact. - dispatch(deleteEntities([entityId], entityType, { preserveLists: true })); - - return api.delete(endpoints.delete.replaceAll(':id', entityId)).then((response) => { - // Success - finish deleting entity from the state. - dispatch(deleteEntities([entityId], entityType)); - - return { - response, - }; - }).catch((e) => { - if (entity) { - // If the API failed, reimport the entity. - dispatch(importEntities([entity], entityType)); - } - throw e; - }); - } - return { createEntity: createEntity, deleteEntity: endpoints.delete ? deleteEntity : undefined,