'use client' import * as React from 'react' import { useSyncExternalStore } from './useSyncExternalStore' import type { MutationFunction, MutationKey } from '@tanstack/query-core' import { notifyManager, parseMutationArgs, MutationObserver, } from '@tanstack/query-core' import { useQueryClient } from './QueryClientProvider' import type { UseMutateFunction, UseMutationOptions, UseMutationResult, } from './types' import { shouldThrowError } from './utils' // HOOK export function useMutation< TData = unknown, TError = unknown, TVariables = void, TContext = unknown, >( options: UseMutationOptions, ): UseMutationResult export function useMutation< TData = unknown, TError = unknown, TVariables = void, TContext = unknown, >( mutationFn: MutationFunction, options?: Omit< UseMutationOptions, 'mutationFn' >, ): UseMutationResult export function useMutation< TData = unknown, TError = unknown, TVariables = void, TContext = unknown, >( mutationKey: MutationKey, options?: Omit< UseMutationOptions, 'mutationKey' >, ): UseMutationResult export function useMutation< TData = unknown, TError = unknown, TVariables = void, TContext = unknown, >( mutationKey: MutationKey, mutationFn?: MutationFunction, options?: Omit< UseMutationOptions, 'mutationKey' | 'mutationFn' >, ): UseMutationResult export function useMutation< TData = unknown, TError = unknown, TVariables = void, TContext = unknown, >( arg1: | MutationKey | MutationFunction | UseMutationOptions, arg2?: | MutationFunction | UseMutationOptions, arg3?: UseMutationOptions, ): UseMutationResult { const options = parseMutationArgs(arg1, arg2, arg3) const queryClient = useQueryClient({ context: options.context }) const [observer] = React.useState( () => new MutationObserver( queryClient, options, ), ) React.useEffect(() => { observer.setOptions(options) }, [observer, options]) const result = useSyncExternalStore( React.useCallback( (onStoreChange) => observer.subscribe(notifyManager.batchCalls(onStoreChange)), [observer], ), () => observer.getCurrentResult(), () => observer.getCurrentResult(), ) const mutate = React.useCallback< UseMutateFunction >( (variables, mutateOptions) => { observer.mutate(variables, mutateOptions).catch(noop) }, [observer], ) if ( result.error && shouldThrowError(observer.options.useErrorBoundary, [result.error]) ) { throw result.error } return { ...result, mutate, mutateAsync: result.mutate } } // eslint-disable-next-line @typescript-eslint/no-empty-function function noop() {}