Skip to content

Instantly share code, notes, and snippets.

@mikecann
Created October 16, 2025 02:55
Show Gist options
  • Select an option

  • Save mikecann/43909780592be737d82da7989ec55d5a to your computer and use it in GitHub Desktop.

Select an option

Save mikecann/43909780592be737d82da7989ec55d5a to your computer and use it in GitHub Desktop.
import { ReactMutation, useMutation } from "convex/react";
import { FunctionReference, OptionalRestArgs } from "convex/server";
import { useCallback, useMemo } from "react";
type VoidReactMutation<M extends FunctionReference<"mutation">> = {
(...args: OptionalRestArgs<M>): void;
withOptimisticUpdate: (
update: Parameters<ReactMutation<M>["withOptimisticUpdate"]>[0],
) => VoidReactMutation<M>;
};
export const useErrorCatchingMutation = <
Mutation extends FunctionReference<"mutation">,
>(
mutation: Mutation,
): VoidReactMutation<Mutation> => {
const callback = useMutation(mutation);
const onApiError = useErrorHandler();
return useMemo(() => {
const wrap = (m: ReactMutation<Mutation>): VoidReactMutation<Mutation> => {
const invoke = (...args: OptionalRestArgs<Mutation>): void => {
void m(...args).catch((err: unknown) => {
onApiError(err);
});
};
const withOptimisticUpdate = (
update: Parameters<typeof m.withOptimisticUpdate>[0],
) => wrap(m.withOptimisticUpdate(update));
return Object.assign(invoke, { withOptimisticUpdate });
};
return wrap(callback);
}, [callback, onApiError]);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment