@@ -6,12 +6,9 @@ import {
66 computed ,
77 inject ,
88 signal ,
9+ untracked ,
910} from '@angular/core'
10- import {
11- QueryClient ,
12- notifyManager ,
13- replaceEqualDeep ,
14- } from '@tanstack/query-core'
11+ import { QueryClient , replaceEqualDeep } from '@tanstack/query-core'
1512import type { Signal } from '@angular/core'
1613import type {
1714 Mutation ,
@@ -53,12 +50,12 @@ export interface InjectMutationStateOptions {
5350
5451/**
5552 * Injects a signal that tracks the state of all mutations.
56- * @param injectMutationStateFn - A function that returns mutation state options.
53+ * @param mutationStateFn - A function that returns mutation state options.
5754 * @param options - The Angular injector to use.
5855 * @returns The signal that tracks the state of all mutations.
5956 */
6057export function injectMutationState < TResult = MutationState > (
61- injectMutationStateFn : ( ) => MutationStateOptions < TResult > = ( ) => ( { } ) ,
58+ mutationStateFn : ( ) => MutationStateOptions < TResult > = ( ) => ( { } ) ,
6259 options ?: InjectMutationStateOptions ,
6360) : Signal < Array < TResult > > {
6461 ! options ?. injector && assertInInjectionContext ( injectMutationState )
@@ -69,53 +66,32 @@ export function injectMutationState<TResult = MutationState>(
6966 const mutationCache = queryClient . getMutationCache ( )
7067
7168 /**
72- * Computed signal that gets result from mutation cache based on passed options
73- * First element is the result, second element is the time when the result was set
74- */
75- const resultFromOptionsSignal = computed ( ( ) => {
76- return [
77- getResult ( mutationCache , injectMutationStateFn ( ) ) ,
78- performance . now ( ) ,
79- ] as const
80- } )
81-
82- /**
83- * Signal that contains result set by subscriber
84- * First element is the result, second element is the time when the result was set
69+ * Returning a writable signal from a computed is similar to `linkedSignal`,
70+ * but compatible with Angular < 19
71+ *
72+ * Compared to `linkedSignal`, this pattern requires extra parentheses:
73+ * - Accessing value: `result()()`
74+ * - Setting value: `result().set(newValue)`
8575 */
86- const resultFromSubscriberSignal = signal < [ Array < TResult > , number ] | null > (
87- null ,
76+ const linkedStateSignal = computed ( ( ) =>
77+ signal ( getResult ( mutationCache , mutationStateFn ( ) ) ) ,
8878 )
8979
90- /**
91- * Returns the last result by either subscriber or options
92- */
93- const effectiveResultSignal = computed ( ( ) => {
94- const optionsResult = resultFromOptionsSignal ( )
95- const subscriberResult = resultFromSubscriberSignal ( )
96- return subscriberResult && subscriberResult [ 1 ] > optionsResult [ 1 ]
97- ? subscriberResult [ 0 ]
98- : optionsResult [ 0 ]
99- } )
80+ const updateMutationState = ( ) =>
81+ ngZone . run ( ( ) =>
82+ untracked ( ( ) =>
83+ linkedStateSignal ( ) . update ( ( current ) => {
84+ const next = getResult ( mutationCache , mutationStateFn ( ) )
85+ return replaceEqualDeep ( current , next )
86+ } ) ,
87+ ) ,
88+ )
10089
10190 const unsubscribe = ngZone . runOutsideAngular ( ( ) =>
102- mutationCache . subscribe (
103- notifyManager . batchCalls ( ( ) => {
104- const [ lastResult ] = effectiveResultSignal ( )
105- const nextResult = replaceEqualDeep (
106- lastResult ,
107- getResult ( mutationCache , injectMutationStateFn ( ) ) ,
108- )
109- if ( lastResult !== nextResult ) {
110- ngZone . run ( ( ) => {
111- resultFromSubscriberSignal . set ( [ nextResult , performance . now ( ) ] )
112- } )
113- }
114- } ) ,
115- ) ,
91+ mutationCache . subscribe ( updateMutationState ) ,
11692 )
11793
11894 destroyRef . onDestroy ( unsubscribe )
11995
120- return effectiveResultSignal
96+ return computed ( ( ) => linkedStateSignal ( ) ( ) )
12197}
0 commit comments