useDeleteEntity: refactor with EntityRequest

environments/review-entity-req-kj3acp/deployments/2962
Alex Gleason 2 years ago
parent 50f65bc7c9
commit 1c5a6d8b41
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7

@ -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…
Cancel
Save