fix: only tanstack usage in optimistic updates
This commit is contained in:
@ -1,5 +1,9 @@
|
||||
import React from "react";
|
||||
import { useMutation, UseMutationOptions } from "@tanstack/react-query";
|
||||
import {
|
||||
useMutation,
|
||||
UseMutationOptions,
|
||||
useQueryClient,
|
||||
} from "@tanstack/react-query";
|
||||
import { AxiosError } from "axios";
|
||||
import { Text } from "@mantine/core";
|
||||
import { modals } from "@mantine/modals";
|
||||
@ -20,9 +24,8 @@ type CrudOperations<TEntity, TUpdate> = {
|
||||
};
|
||||
|
||||
type UseEntityOperationsProps<TEntity extends BaseEntity, TUpdate, TCreate> = {
|
||||
entities: TEntity[];
|
||||
setEntities: React.Dispatch<React.SetStateAction<TEntity[]>>;
|
||||
refetch: () => void;
|
||||
key: string;
|
||||
queryKey: any[];
|
||||
mutations: {
|
||||
create: UseMutationOptions<
|
||||
any,
|
||||
@ -50,9 +53,8 @@ const useCrudOperations = <
|
||||
TUpdate extends object,
|
||||
TCreate extends object,
|
||||
>({
|
||||
entities,
|
||||
setEntities,
|
||||
refetch,
|
||||
key,
|
||||
queryKey,
|
||||
mutations,
|
||||
getCreateEntity,
|
||||
getUpdateEntity,
|
||||
@ -61,30 +63,81 @@ const useCrudOperations = <
|
||||
TEntity,
|
||||
TUpdate
|
||||
> => {
|
||||
const onError = (error: AxiosError<HttpValidationError>) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const onError = (
|
||||
error: AxiosError<HttpValidationError>,
|
||||
_: any,
|
||||
context: any
|
||||
) => {
|
||||
console.error(error);
|
||||
notifications.error({
|
||||
message: error.response?.data?.detail as string | undefined,
|
||||
});
|
||||
refetch();
|
||||
if (context?.previous) {
|
||||
queryClient.setQueryData(queryKey, context.previous);
|
||||
}
|
||||
};
|
||||
|
||||
const onSettled = () => queryClient.invalidateQueries({ queryKey });
|
||||
|
||||
const createMutation = useMutation({
|
||||
...mutations.create,
|
||||
onError,
|
||||
onSuccess: (res: { entity: TEntity }) => {
|
||||
setEntities([...entities, res.entity]);
|
||||
},
|
||||
onSettled,
|
||||
});
|
||||
|
||||
const updateMutation = useMutation({
|
||||
...mutations.update,
|
||||
onError,
|
||||
onSettled,
|
||||
onMutate: async ({ body: { entity: update } }) => {
|
||||
await queryClient.cancelQueries({ queryKey: [key] });
|
||||
|
||||
const previous = queryClient.getQueryData(queryKey);
|
||||
|
||||
queryClient.setQueryData(queryKey, (old: { items: TEntity[] }) => {
|
||||
let updated = old.items.map((entity: TEntity) =>
|
||||
entity.id === update.id
|
||||
? getUpdateEntity(entity, update)
|
||||
: entity
|
||||
);
|
||||
|
||||
if ("lexorank" in update) {
|
||||
updated = sortByLexorank(
|
||||
updated as (TEntity & { lexorank: string })[]
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...old,
|
||||
items: updated,
|
||||
};
|
||||
});
|
||||
|
||||
return { previous };
|
||||
},
|
||||
});
|
||||
|
||||
const deleteMutation = useMutation({
|
||||
...mutations.delete,
|
||||
onError,
|
||||
onSettled,
|
||||
onMutate: async ({ path: { pk } }) => {
|
||||
await queryClient.cancelQueries({ queryKey: [key] });
|
||||
|
||||
const previous = queryClient.getQueryData(queryKey);
|
||||
|
||||
queryClient.setQueryData(queryKey, (old: { items: TEntity[] }) => {
|
||||
const filtered = old.items.filter(e => e.id !== pk);
|
||||
return {
|
||||
...old,
|
||||
items: filtered,
|
||||
};
|
||||
});
|
||||
|
||||
return { previous };
|
||||
},
|
||||
});
|
||||
|
||||
const onCreate = (name: string) => {
|
||||
@ -99,7 +152,7 @@ const useCrudOperations = <
|
||||
});
|
||||
};
|
||||
|
||||
const onUpdate = (id: number, update: TUpdate) => {
|
||||
const onUpdate = async (id: number, update: TUpdate) => {
|
||||
updateMutation.mutate({
|
||||
body: {
|
||||
entity: update,
|
||||
@ -107,17 +160,6 @@ const useCrudOperations = <
|
||||
path: { pk: id },
|
||||
query: undefined,
|
||||
});
|
||||
setEntities(prev => {
|
||||
const updated = prev.map(entity =>
|
||||
entity.id === id ? getUpdateEntity(entity, update) : entity
|
||||
);
|
||||
if ("lexorank" in update) {
|
||||
return sortByLexorank(
|
||||
updated as (TEntity & { lexorank: string })[]
|
||||
);
|
||||
}
|
||||
return updated;
|
||||
});
|
||||
};
|
||||
|
||||
const onDelete = (entity: TEntity, onSuccess?: () => void) => {
|
||||
@ -131,7 +173,6 @@ const useCrudOperations = <
|
||||
onConfirm: () => {
|
||||
deleteMutation.mutate({ path: { pk: entity.id } } as any);
|
||||
onSuccess && onSuccess();
|
||||
setEntities(prev => prev.filter(e => e.id !== entity.id));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user