Files
yaak/apps/yaak-client/hooks/useFastMutation.ts
Gregory Schier 7314aedc71 Merge main into proxy branch (formatting and docs)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:09:59 -07:00

77 lines
2.3 KiB
TypeScript

import type { MutationKey } from "@tanstack/react-query";
import { useMemo } from "react";
import { showToast } from "../lib/toast";
interface MutationOptions<TData, TError, TVariables> {
mutationKey: MutationKey;
mutationFn: (vars: TVariables) => Promise<TData>;
onSettled?: () => void;
onError?: (err: TError) => void;
onSuccess?: (data: TData) => void;
disableToastError?: boolean;
}
type CallbackMutationOptions<TData, TError, TVariables> = Omit<
MutationOptions<TData, TError, TVariables>,
"mutationKey" | "mutationFn"
>;
export function createFastMutation<TData = unknown, TError = unknown, TVariables = void>(
defaultArgs: MutationOptions<TData, TError, TVariables>,
) {
const mutateAsync = async (
variables: TVariables,
args?: CallbackMutationOptions<TData, TError, TVariables>,
) => {
const { mutationKey, mutationFn, disableToastError } = {
...defaultArgs,
...args,
};
try {
const data = await mutationFn(variables);
// Run both default and custom onSuccess callbacks
defaultArgs.onSuccess?.(data);
args?.onSuccess?.(data);
defaultArgs.onSettled?.();
args?.onSettled?.();
return data;
} catch (err: unknown) {
const stringKey = mutationKey.join(".");
const e = err as TError;
console.log("mutation error", stringKey, e);
if (!disableToastError) {
showToast({
id: stringKey,
message: err instanceof Error ? err.message : String(err),
color: "danger",
timeout: 5000,
});
}
// Run both default and custom onError callbacks
defaultArgs.onError?.(e);
args?.onError?.(e);
defaultArgs.onSettled?.();
args?.onSettled?.();
throw e;
}
};
const mutate = (
variables: TVariables,
args?: CallbackMutationOptions<TData, TError, TVariables>,
) => {
setTimeout(() => mutateAsync(variables, args));
};
return { mutateAsync, mutate };
}
export function useFastMutation<TData = unknown, TError = unknown, TVariables = void>(
defaultArgs: MutationOptions<TData, TError, TVariables>,
) {
return useMemo(() => {
return createFastMutation(defaultArgs);
// oxlint-disable-next-line react-hooks/exhaustive-deps -- Force it!
}, defaultArgs.mutationKey);
}