| 91 | * ``` |
| 92 | */ |
| 93 | export function usePacedMutations< |
| 94 | TVariables = unknown, |
| 95 | T extends object = Record<string, unknown>, |
| 96 | >( |
| 97 | config: PacedMutationsConfig<TVariables, T>, |
| 98 | ): (variables: TVariables) => Transaction<T> { |
| 99 | // Keep refs to the latest callbacks so we can call them without recreating the instance |
| 100 | const onMutateRef = useRef(config.onMutate) |
| 101 | onMutateRef.current = config.onMutate |
| 102 | |
| 103 | const mutationFnRef = useRef(config.mutationFn) |
| 104 | mutationFnRef.current = config.mutationFn |
| 105 | |
| 106 | // Create stable wrappers that always call the latest version |
| 107 | const stableOnMutate = useCallback<typeof config.onMutate>((variables) => { |
| 108 | return onMutateRef.current(variables) |
| 109 | }, []) |
| 110 | |
| 111 | const stableMutationFn = useCallback<typeof config.mutationFn>((params) => { |
| 112 | return mutationFnRef.current(params) |
| 113 | }, []) |
| 114 | |
| 115 | // Create paced mutations instance with proper dependency tracking |
| 116 | // Serialize strategy for stable comparison since strategy objects are recreated on each render |
| 117 | const mutate = useMemo(() => { |
| 118 | return createPacedMutations<TVariables, T>({ |
| 119 | ...config, |
| 120 | onMutate: stableOnMutate, |
| 121 | mutationFn: stableMutationFn, |
| 122 | }) |
| 123 | }, [ |
| 124 | stableOnMutate, |
| 125 | stableMutationFn, |
| 126 | config.metadata, |
| 127 | // Serialize strategy to avoid recreating when object reference changes but values are same |
| 128 | JSON.stringify({ |
| 129 | type: config.strategy._type, |
| 130 | options: config.strategy.options, |
| 131 | }), |
| 132 | ]) |
| 133 | |
| 134 | // Return stable mutate callback |
| 135 | const stableMutate = useCallback(mutate, [mutate]) |
| 136 | |
| 137 | return stableMutate |
| 138 | } |