import * as React from 'react' import { MutationCache, MutationInfoFilters, QueryClient } from '../vanilla' import { MutationInfo, MutationInfoState } from '../vanilla/mutationInfo' import { replaceEqualDeep } from '../vanilla/utils' import { useQueryClient } from './QueryClientProvider' export function useIsMutating( filters?: MutationInfoFilters, queryClient?: QueryClient ): number { const client = useQueryClient(queryClient) return useMutationState( { filters: { ...filters, status: 'mutating' } }, client ).length } type MutationStateOptions< TData = unknown, TVars = unknown, TError = Error, TResult = MutationInfoState > = { filters?: MutationInfoFilters select?: (mutationInfo: MutationInfo) => TResult } function getResult< TData = unknown, TVars = unknown, TError = Error, TResult = MutationInfoState >( mutationCache: MutationCache, options: MutationStateOptions ): Array { return mutationCache .findAll(options.filters) .map( (mutation): TResult => (options.select ? options.select(mutation) : mutation.state) as TResult ) } export function useMutationState< TData = unknown, TVars = unknown, TError = Error, TResult = MutationInfoState >( options: MutationStateOptions = {}, queryClient?: QueryClient ): Array { const mutationCache = useQueryClient(queryClient).getMutationCache() const optionsRef = React.useRef(options) const result = React.useRef>() if (!result.current) { result.current = getResult(mutationCache, options) } React.useEffect(() => { optionsRef.current = options }) return React.useSyncExternalStore( React.useCallback( onStoreChange => mutationCache.subscribe(() => { const nextResult = replaceEqualDeep( result.current, getResult(mutationCache, optionsRef.current) ) if (result.current !== nextResult) { result.current = nextResult onStoreChange() } }), [mutationCache] ), () => result.current, () => result.current )! }