@tanstack/solid-query 6.0.0-beta.3 → 6.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/dev.cjs +75 -51
- package/build/dev.js +76 -52
- package/build/index.cjs +75 -51
- package/build/index.js +76 -52
- package/package.json +5 -5
- package/src/useBaseQuery.ts +102 -44
- package/src/useIsFetching.ts +1 -1
- package/src/useIsMutating.ts +1 -1
- package/src/useMutationState.ts +1 -1
- package/src/useQueries.ts +21 -16
package/build/dev.cjs
CHANGED
|
@@ -93,10 +93,10 @@ var hydratableObserverResult = (query, result) => {
|
|
|
93
93
|
return obj;
|
|
94
94
|
};
|
|
95
95
|
function useBaseQuery(options, Observer, queryClient) {
|
|
96
|
-
const client = solidJs.
|
|
96
|
+
const [client] = solidJs.createSignal(() => exports.useQueryClient(queryClient?.()));
|
|
97
97
|
const isRestoring = exports.useIsRestoring();
|
|
98
98
|
let unsubscribeQueued = false;
|
|
99
|
-
const defaultedOptions = solidJs.
|
|
99
|
+
const [defaultedOptions] = solidJs.createSignal(() => {
|
|
100
100
|
const defaultOptions = client().defaultQueryOptions(options());
|
|
101
101
|
defaultOptions._optimisticResults = isRestoring() ? "isRestoring" : "optimistic";
|
|
102
102
|
defaultOptions.structuralSharing = false;
|
|
@@ -108,11 +108,11 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
108
108
|
return defaultOptions;
|
|
109
109
|
});
|
|
110
110
|
const observer = solidJs.untrack(() => new Observer(client(), defaultedOptions()));
|
|
111
|
-
const trackedDefaultedOptions = solidJs.
|
|
111
|
+
const [trackedDefaultedOptions] = solidJs.createSignal(() => defaultedOptions());
|
|
112
112
|
solidJs.createRenderEffect(
|
|
113
113
|
() => trackedDefaultedOptions(),
|
|
114
114
|
(opts) => {
|
|
115
|
-
observer.setOptions(opts);
|
|
115
|
+
solidJs.runWithOwner(null, () => observer.setOptions(opts));
|
|
116
116
|
}
|
|
117
117
|
);
|
|
118
118
|
let observerResult = solidJs.untrack(
|
|
@@ -146,8 +146,8 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
146
146
|
return observer.subscribe((result) => {
|
|
147
147
|
const previousResult = observerResult;
|
|
148
148
|
observerResult = result;
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
solidJs.runWithOwner(null, () => {
|
|
150
|
+
setStateWithReconciliation(result);
|
|
151
151
|
if (unsubscribe && !disposed && (previousResult.isLoading !== result.isLoading || previousResult.isError !== result.isError)) {
|
|
152
152
|
try {
|
|
153
153
|
solidJs.refresh(queryResource);
|
|
@@ -173,41 +173,58 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
173
173
|
let unsubscribe = null;
|
|
174
174
|
let disposed = false;
|
|
175
175
|
let resolver = null;
|
|
176
|
-
const queryResource = solidJs.
|
|
177
|
-
()
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
176
|
+
const [queryResource] = solidJs.createSignal(() => {
|
|
177
|
+
const opts = trackedDefaultedOptions();
|
|
178
|
+
const restoring = isRestoring();
|
|
179
|
+
if (isServer) {
|
|
180
|
+
const cached = observer.getOptimisticResult(opts);
|
|
181
|
+
if (!cached.isLoading) {
|
|
182
|
+
observerResult = cached;
|
|
183
|
+
solidJs.runWithOwner(null, () => {
|
|
184
|
+
setStateWithReconciliation(cached);
|
|
185
|
+
});
|
|
186
|
+
return hydratableObserverResult(
|
|
187
|
+
observer.getCurrentQuery(),
|
|
188
|
+
cached
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return new Promise((resolve, reject) => {
|
|
193
|
+
resolver = resolve;
|
|
194
|
+
if (isServer) {
|
|
195
|
+
unsubscribe = createServerSubscriber((data) => {
|
|
196
|
+
resolve(data);
|
|
197
|
+
}, reject);
|
|
198
|
+
} else if (!unsubscribe && !restoring) {
|
|
199
|
+
unsubscribe = createClientSubscriber();
|
|
200
|
+
}
|
|
201
|
+
const currentResult = observer.getOptimisticResult(opts);
|
|
202
|
+
observerResult = currentResult;
|
|
203
|
+
solidJs.runWithOwner(null, () => {
|
|
191
204
|
if (currentResult.isError && !currentResult.isFetching && !restoring && queryCore.shouldThrowError(opts.throwOnError, [
|
|
192
205
|
currentResult.error,
|
|
193
206
|
observer.getCurrentQuery()
|
|
194
207
|
])) {
|
|
195
208
|
setStateWithReconciliation(currentResult);
|
|
196
|
-
|
|
209
|
+
reject(currentResult.error);
|
|
210
|
+
return;
|
|
197
211
|
}
|
|
198
|
-
|
|
199
|
-
resolver = null;
|
|
200
|
-
setStateWithReconciliation(currentResult);
|
|
201
|
-
return resolve(
|
|
202
|
-
hydratableObserverResult(observer.getCurrentQuery(), currentResult)
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
|
-
queueMicrotask(() => setStateWithReconciliation(currentResult));
|
|
212
|
+
setStateWithReconciliation(currentResult);
|
|
206
213
|
});
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
214
|
+
if (currentResult.isError && !currentResult.isFetching && !restoring && queryCore.shouldThrowError(opts.throwOnError, [
|
|
215
|
+
currentResult.error,
|
|
216
|
+
observer.getCurrentQuery()
|
|
217
|
+
])) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (!currentResult.isLoading) {
|
|
221
|
+
resolver = null;
|
|
222
|
+
return resolve(
|
|
223
|
+
hydratableObserverResult(observer.getCurrentQuery(), currentResult)
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
});
|
|
211
228
|
solidJs.onCleanup(() => {
|
|
212
229
|
disposed = true;
|
|
213
230
|
if (isServer && solidJs.isPending(queryResource)) {
|
|
@@ -236,6 +253,9 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
236
253
|
if (typeof prop === "symbol") {
|
|
237
254
|
return Reflect.get(target, prop, receiver);
|
|
238
255
|
}
|
|
256
|
+
if (isServer) {
|
|
257
|
+
queryResource();
|
|
258
|
+
}
|
|
239
259
|
if (errorPassthroughProps.has(prop)) {
|
|
240
260
|
return Reflect.get(target, prop, receiver);
|
|
241
261
|
}
|
|
@@ -345,14 +365,16 @@ function useQueries(queriesOptions, queryClient) {
|
|
|
345
365
|
() => {
|
|
346
366
|
if (!isRestoring()) {
|
|
347
367
|
unsubscribe = observer.subscribe((result) => {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
368
|
+
solidJs.runWithOwner(null, () => {
|
|
369
|
+
setState(
|
|
370
|
+
solidJs.reconcile(
|
|
371
|
+
[...result],
|
|
372
|
+
// Use a key function that returns undefined so reconcile
|
|
373
|
+
// uses positional matching and recursively updates nested properties
|
|
374
|
+
() => void 0
|
|
375
|
+
)
|
|
376
|
+
);
|
|
377
|
+
});
|
|
356
378
|
});
|
|
357
379
|
}
|
|
358
380
|
},
|
|
@@ -364,12 +386,14 @@ function useQueries(queriesOptions, queryClient) {
|
|
|
364
386
|
});
|
|
365
387
|
solidJs.createMemo(() => {
|
|
366
388
|
const queries = defaultedQueries();
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
389
|
+
solidJs.runWithOwner(null, () => {
|
|
390
|
+
observer.setQueries(
|
|
391
|
+
queries,
|
|
392
|
+
queriesOptions().combine ? {
|
|
393
|
+
combine: queriesOptions().combine
|
|
394
|
+
} : void 0
|
|
395
|
+
);
|
|
396
|
+
});
|
|
373
397
|
return queries;
|
|
374
398
|
});
|
|
375
399
|
return state;
|
|
@@ -389,7 +413,7 @@ function useIsFetching(filters, queryClient) {
|
|
|
389
413
|
const queryCache = solidJs.createMemo(() => client().getQueryCache());
|
|
390
414
|
const [fetches, setFetches] = solidJs.createSignal(
|
|
391
415
|
solidJs.untrack(() => client().isFetching(filters?.())),
|
|
392
|
-
{
|
|
416
|
+
{ ownedWrite: true }
|
|
393
417
|
);
|
|
394
418
|
const unsubscribe = solidJs.untrack(
|
|
395
419
|
() => queryCache().subscribe(() => {
|
|
@@ -414,7 +438,7 @@ function useIsMutating(filters, queryClient) {
|
|
|
414
438
|
const mutationCache = solidJs.createMemo(() => client().getMutationCache());
|
|
415
439
|
const [mutations, setMutations] = solidJs.createSignal(
|
|
416
440
|
solidJs.untrack(() => client().isMutating(filters?.())),
|
|
417
|
-
{
|
|
441
|
+
{ ownedWrite: true }
|
|
418
442
|
);
|
|
419
443
|
const unsubscribe = solidJs.untrack(
|
|
420
444
|
() => mutationCache().subscribe((_result) => {
|
|
@@ -434,7 +458,7 @@ function useMutationState(options = () => ({}), queryClient) {
|
|
|
434
458
|
const mutationCache = solidJs.createMemo(() => client().getMutationCache());
|
|
435
459
|
const [result, setResult] = solidJs.createSignal(
|
|
436
460
|
solidJs.untrack(() => getResult(mutationCache(), options())),
|
|
437
|
-
{
|
|
461
|
+
{ ownedWrite: true }
|
|
438
462
|
);
|
|
439
463
|
const unsubscribe = solidJs.untrack(
|
|
440
464
|
() => mutationCache().subscribe(() => {
|
package/build/dev.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MutationObserver, shouldThrowError, QueriesObserver, QueryClient as QueryClient$1, replaceEqualDeep, noop, notifyManager, QueryObserver, InfiniteQueryObserver } from '@tanstack/query-core';
|
|
2
2
|
export * from '@tanstack/query-core';
|
|
3
|
-
import { createContext, useContext, onCleanup, createMemo, untrack, createRenderEffect, createStore, merge, createEffect, reconcile, createSignal, isPending, refresh, snapshot } from 'solid-js';
|
|
3
|
+
import { createContext, useContext, onCleanup, createMemo, untrack, createRenderEffect, createStore, merge, createEffect, runWithOwner, reconcile, createSignal, isPending, refresh, snapshot } from 'solid-js';
|
|
4
4
|
import { createComponent } from '@solidjs/web';
|
|
5
5
|
|
|
6
6
|
// src/useQuery.ts
|
|
@@ -92,10 +92,10 @@ var hydratableObserverResult = (query, result) => {
|
|
|
92
92
|
return obj;
|
|
93
93
|
};
|
|
94
94
|
function useBaseQuery(options, Observer, queryClient) {
|
|
95
|
-
const client =
|
|
95
|
+
const [client] = createSignal(() => useQueryClient(queryClient?.()));
|
|
96
96
|
const isRestoring = useIsRestoring();
|
|
97
97
|
let unsubscribeQueued = false;
|
|
98
|
-
const defaultedOptions =
|
|
98
|
+
const [defaultedOptions] = createSignal(() => {
|
|
99
99
|
const defaultOptions = client().defaultQueryOptions(options());
|
|
100
100
|
defaultOptions._optimisticResults = isRestoring() ? "isRestoring" : "optimistic";
|
|
101
101
|
defaultOptions.structuralSharing = false;
|
|
@@ -107,11 +107,11 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
107
107
|
return defaultOptions;
|
|
108
108
|
});
|
|
109
109
|
const observer = untrack(() => new Observer(client(), defaultedOptions()));
|
|
110
|
-
const trackedDefaultedOptions =
|
|
110
|
+
const [trackedDefaultedOptions] = createSignal(() => defaultedOptions());
|
|
111
111
|
createRenderEffect(
|
|
112
112
|
() => trackedDefaultedOptions(),
|
|
113
113
|
(opts) => {
|
|
114
|
-
observer.setOptions(opts);
|
|
114
|
+
runWithOwner(null, () => observer.setOptions(opts));
|
|
115
115
|
}
|
|
116
116
|
);
|
|
117
117
|
let observerResult = untrack(
|
|
@@ -145,8 +145,8 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
145
145
|
return observer.subscribe((result) => {
|
|
146
146
|
const previousResult = observerResult;
|
|
147
147
|
observerResult = result;
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
runWithOwner(null, () => {
|
|
149
|
+
setStateWithReconciliation(result);
|
|
150
150
|
if (unsubscribe && !disposed && (previousResult.isLoading !== result.isLoading || previousResult.isError !== result.isError)) {
|
|
151
151
|
try {
|
|
152
152
|
refresh(queryResource);
|
|
@@ -172,41 +172,58 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
172
172
|
let unsubscribe = null;
|
|
173
173
|
let disposed = false;
|
|
174
174
|
let resolver = null;
|
|
175
|
-
const queryResource =
|
|
176
|
-
()
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
175
|
+
const [queryResource] = createSignal(() => {
|
|
176
|
+
const opts = trackedDefaultedOptions();
|
|
177
|
+
const restoring = isRestoring();
|
|
178
|
+
if (isServer) {
|
|
179
|
+
const cached = observer.getOptimisticResult(opts);
|
|
180
|
+
if (!cached.isLoading) {
|
|
181
|
+
observerResult = cached;
|
|
182
|
+
runWithOwner(null, () => {
|
|
183
|
+
setStateWithReconciliation(cached);
|
|
184
|
+
});
|
|
185
|
+
return hydratableObserverResult(
|
|
186
|
+
observer.getCurrentQuery(),
|
|
187
|
+
cached
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return new Promise((resolve, reject) => {
|
|
192
|
+
resolver = resolve;
|
|
193
|
+
if (isServer) {
|
|
194
|
+
unsubscribe = createServerSubscriber((data) => {
|
|
195
|
+
resolve(data);
|
|
196
|
+
}, reject);
|
|
197
|
+
} else if (!unsubscribe && !restoring) {
|
|
198
|
+
unsubscribe = createClientSubscriber();
|
|
199
|
+
}
|
|
200
|
+
const currentResult = observer.getOptimisticResult(opts);
|
|
201
|
+
observerResult = currentResult;
|
|
202
|
+
runWithOwner(null, () => {
|
|
190
203
|
if (currentResult.isError && !currentResult.isFetching && !restoring && shouldThrowError(opts.throwOnError, [
|
|
191
204
|
currentResult.error,
|
|
192
205
|
observer.getCurrentQuery()
|
|
193
206
|
])) {
|
|
194
207
|
setStateWithReconciliation(currentResult);
|
|
195
|
-
|
|
208
|
+
reject(currentResult.error);
|
|
209
|
+
return;
|
|
196
210
|
}
|
|
197
|
-
|
|
198
|
-
resolver = null;
|
|
199
|
-
setStateWithReconciliation(currentResult);
|
|
200
|
-
return resolve(
|
|
201
|
-
hydratableObserverResult(observer.getCurrentQuery(), currentResult)
|
|
202
|
-
);
|
|
203
|
-
}
|
|
204
|
-
queueMicrotask(() => setStateWithReconciliation(currentResult));
|
|
211
|
+
setStateWithReconciliation(currentResult);
|
|
205
212
|
});
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
213
|
+
if (currentResult.isError && !currentResult.isFetching && !restoring && shouldThrowError(opts.throwOnError, [
|
|
214
|
+
currentResult.error,
|
|
215
|
+
observer.getCurrentQuery()
|
|
216
|
+
])) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (!currentResult.isLoading) {
|
|
220
|
+
resolver = null;
|
|
221
|
+
return resolve(
|
|
222
|
+
hydratableObserverResult(observer.getCurrentQuery(), currentResult)
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
});
|
|
210
227
|
onCleanup(() => {
|
|
211
228
|
disposed = true;
|
|
212
229
|
if (isServer && isPending(queryResource)) {
|
|
@@ -235,6 +252,9 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
235
252
|
if (typeof prop === "symbol") {
|
|
236
253
|
return Reflect.get(target, prop, receiver);
|
|
237
254
|
}
|
|
255
|
+
if (isServer) {
|
|
256
|
+
queryResource();
|
|
257
|
+
}
|
|
238
258
|
if (errorPassthroughProps.has(prop)) {
|
|
239
259
|
return Reflect.get(target, prop, receiver);
|
|
240
260
|
}
|
|
@@ -344,14 +364,16 @@ function useQueries(queriesOptions, queryClient) {
|
|
|
344
364
|
() => {
|
|
345
365
|
if (!isRestoring()) {
|
|
346
366
|
unsubscribe = observer.subscribe((result) => {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
367
|
+
runWithOwner(null, () => {
|
|
368
|
+
setState(
|
|
369
|
+
reconcile(
|
|
370
|
+
[...result],
|
|
371
|
+
// Use a key function that returns undefined so reconcile
|
|
372
|
+
// uses positional matching and recursively updates nested properties
|
|
373
|
+
() => void 0
|
|
374
|
+
)
|
|
375
|
+
);
|
|
376
|
+
});
|
|
355
377
|
});
|
|
356
378
|
}
|
|
357
379
|
},
|
|
@@ -363,12 +385,14 @@ function useQueries(queriesOptions, queryClient) {
|
|
|
363
385
|
});
|
|
364
386
|
createMemo(() => {
|
|
365
387
|
const queries = defaultedQueries();
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
388
|
+
runWithOwner(null, () => {
|
|
389
|
+
observer.setQueries(
|
|
390
|
+
queries,
|
|
391
|
+
queriesOptions().combine ? {
|
|
392
|
+
combine: queriesOptions().combine
|
|
393
|
+
} : void 0
|
|
394
|
+
);
|
|
395
|
+
});
|
|
372
396
|
return queries;
|
|
373
397
|
});
|
|
374
398
|
return state;
|
|
@@ -388,7 +412,7 @@ function useIsFetching(filters, queryClient) {
|
|
|
388
412
|
const queryCache = createMemo(() => client().getQueryCache());
|
|
389
413
|
const [fetches, setFetches] = createSignal(
|
|
390
414
|
untrack(() => client().isFetching(filters?.())),
|
|
391
|
-
{
|
|
415
|
+
{ ownedWrite: true }
|
|
392
416
|
);
|
|
393
417
|
const unsubscribe = untrack(
|
|
394
418
|
() => queryCache().subscribe(() => {
|
|
@@ -413,7 +437,7 @@ function useIsMutating(filters, queryClient) {
|
|
|
413
437
|
const mutationCache = createMemo(() => client().getMutationCache());
|
|
414
438
|
const [mutations, setMutations] = createSignal(
|
|
415
439
|
untrack(() => client().isMutating(filters?.())),
|
|
416
|
-
{
|
|
440
|
+
{ ownedWrite: true }
|
|
417
441
|
);
|
|
418
442
|
const unsubscribe = untrack(
|
|
419
443
|
() => mutationCache().subscribe((_result) => {
|
|
@@ -433,7 +457,7 @@ function useMutationState(options = () => ({}), queryClient) {
|
|
|
433
457
|
const mutationCache = createMemo(() => client().getMutationCache());
|
|
434
458
|
const [result, setResult] = createSignal(
|
|
435
459
|
untrack(() => getResult(mutationCache(), options())),
|
|
436
|
-
{
|
|
460
|
+
{ ownedWrite: true }
|
|
437
461
|
);
|
|
438
462
|
const unsubscribe = untrack(
|
|
439
463
|
() => mutationCache().subscribe(() => {
|
package/build/index.cjs
CHANGED
|
@@ -84,10 +84,10 @@ var hydratableObserverResult = (query, result) => {
|
|
|
84
84
|
return obj;
|
|
85
85
|
};
|
|
86
86
|
function useBaseQuery(options, Observer, queryClient) {
|
|
87
|
-
const client = solidJs.
|
|
87
|
+
const [client] = solidJs.createSignal(() => exports.useQueryClient(queryClient?.()));
|
|
88
88
|
const isRestoring = exports.useIsRestoring();
|
|
89
89
|
let unsubscribeQueued = false;
|
|
90
|
-
const defaultedOptions = solidJs.
|
|
90
|
+
const [defaultedOptions] = solidJs.createSignal(() => {
|
|
91
91
|
const defaultOptions = client().defaultQueryOptions(options());
|
|
92
92
|
defaultOptions._optimisticResults = isRestoring() ? "isRestoring" : "optimistic";
|
|
93
93
|
defaultOptions.structuralSharing = false;
|
|
@@ -99,11 +99,11 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
99
99
|
return defaultOptions;
|
|
100
100
|
});
|
|
101
101
|
const observer = solidJs.untrack(() => new Observer(client(), defaultedOptions()));
|
|
102
|
-
const trackedDefaultedOptions = solidJs.
|
|
102
|
+
const [trackedDefaultedOptions] = solidJs.createSignal(() => defaultedOptions());
|
|
103
103
|
solidJs.createRenderEffect(
|
|
104
104
|
() => trackedDefaultedOptions(),
|
|
105
105
|
(opts) => {
|
|
106
|
-
observer.setOptions(opts);
|
|
106
|
+
solidJs.runWithOwner(null, () => observer.setOptions(opts));
|
|
107
107
|
}
|
|
108
108
|
);
|
|
109
109
|
let observerResult = solidJs.untrack(
|
|
@@ -137,8 +137,8 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
137
137
|
return observer.subscribe((result) => {
|
|
138
138
|
const previousResult = observerResult;
|
|
139
139
|
observerResult = result;
|
|
140
|
-
|
|
141
|
-
|
|
140
|
+
solidJs.runWithOwner(null, () => {
|
|
141
|
+
setStateWithReconciliation(result);
|
|
142
142
|
if (unsubscribe && !disposed && (previousResult.isLoading !== result.isLoading || previousResult.isError !== result.isError)) {
|
|
143
143
|
try {
|
|
144
144
|
solidJs.refresh(queryResource);
|
|
@@ -164,41 +164,58 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
164
164
|
let unsubscribe = null;
|
|
165
165
|
let disposed = false;
|
|
166
166
|
let resolver = null;
|
|
167
|
-
const queryResource = solidJs.
|
|
168
|
-
()
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
167
|
+
const [queryResource] = solidJs.createSignal(() => {
|
|
168
|
+
const opts = trackedDefaultedOptions();
|
|
169
|
+
const restoring = isRestoring();
|
|
170
|
+
if (isServer) {
|
|
171
|
+
const cached = observer.getOptimisticResult(opts);
|
|
172
|
+
if (!cached.isLoading) {
|
|
173
|
+
observerResult = cached;
|
|
174
|
+
solidJs.runWithOwner(null, () => {
|
|
175
|
+
setStateWithReconciliation(cached);
|
|
176
|
+
});
|
|
177
|
+
return hydratableObserverResult(
|
|
178
|
+
observer.getCurrentQuery(),
|
|
179
|
+
cached
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return new Promise((resolve, reject) => {
|
|
184
|
+
resolver = resolve;
|
|
185
|
+
if (isServer) {
|
|
186
|
+
unsubscribe = createServerSubscriber((data) => {
|
|
187
|
+
resolve(data);
|
|
188
|
+
}, reject);
|
|
189
|
+
} else if (!unsubscribe && !restoring) {
|
|
190
|
+
unsubscribe = createClientSubscriber();
|
|
191
|
+
}
|
|
192
|
+
const currentResult = observer.getOptimisticResult(opts);
|
|
193
|
+
observerResult = currentResult;
|
|
194
|
+
solidJs.runWithOwner(null, () => {
|
|
182
195
|
if (currentResult.isError && !currentResult.isFetching && !restoring && queryCore.shouldThrowError(opts.throwOnError, [
|
|
183
196
|
currentResult.error,
|
|
184
197
|
observer.getCurrentQuery()
|
|
185
198
|
])) {
|
|
186
199
|
setStateWithReconciliation(currentResult);
|
|
187
|
-
|
|
200
|
+
reject(currentResult.error);
|
|
201
|
+
return;
|
|
188
202
|
}
|
|
189
|
-
|
|
190
|
-
resolver = null;
|
|
191
|
-
setStateWithReconciliation(currentResult);
|
|
192
|
-
return resolve(
|
|
193
|
-
hydratableObserverResult(observer.getCurrentQuery(), currentResult)
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
queueMicrotask(() => setStateWithReconciliation(currentResult));
|
|
203
|
+
setStateWithReconciliation(currentResult);
|
|
197
204
|
});
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
205
|
+
if (currentResult.isError && !currentResult.isFetching && !restoring && queryCore.shouldThrowError(opts.throwOnError, [
|
|
206
|
+
currentResult.error,
|
|
207
|
+
observer.getCurrentQuery()
|
|
208
|
+
])) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (!currentResult.isLoading) {
|
|
212
|
+
resolver = null;
|
|
213
|
+
return resolve(
|
|
214
|
+
hydratableObserverResult(observer.getCurrentQuery(), currentResult)
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
});
|
|
202
219
|
solidJs.onCleanup(() => {
|
|
203
220
|
disposed = true;
|
|
204
221
|
if (isServer && solidJs.isPending(queryResource)) {
|
|
@@ -227,6 +244,9 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
227
244
|
if (typeof prop === "symbol") {
|
|
228
245
|
return Reflect.get(target, prop, receiver);
|
|
229
246
|
}
|
|
247
|
+
if (isServer) {
|
|
248
|
+
queryResource();
|
|
249
|
+
}
|
|
230
250
|
if (errorPassthroughProps.has(prop)) {
|
|
231
251
|
return Reflect.get(target, prop, receiver);
|
|
232
252
|
}
|
|
@@ -336,14 +356,16 @@ function useQueries(queriesOptions, queryClient) {
|
|
|
336
356
|
() => {
|
|
337
357
|
if (!isRestoring()) {
|
|
338
358
|
unsubscribe = observer.subscribe((result) => {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
359
|
+
solidJs.runWithOwner(null, () => {
|
|
360
|
+
setState(
|
|
361
|
+
solidJs.reconcile(
|
|
362
|
+
[...result],
|
|
363
|
+
// Use a key function that returns undefined so reconcile
|
|
364
|
+
// uses positional matching and recursively updates nested properties
|
|
365
|
+
() => void 0
|
|
366
|
+
)
|
|
367
|
+
);
|
|
368
|
+
});
|
|
347
369
|
});
|
|
348
370
|
}
|
|
349
371
|
},
|
|
@@ -355,12 +377,14 @@ function useQueries(queriesOptions, queryClient) {
|
|
|
355
377
|
});
|
|
356
378
|
solidJs.createMemo(() => {
|
|
357
379
|
const queries = defaultedQueries();
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
380
|
+
solidJs.runWithOwner(null, () => {
|
|
381
|
+
observer.setQueries(
|
|
382
|
+
queries,
|
|
383
|
+
queriesOptions().combine ? {
|
|
384
|
+
combine: queriesOptions().combine
|
|
385
|
+
} : void 0
|
|
386
|
+
);
|
|
387
|
+
});
|
|
364
388
|
return queries;
|
|
365
389
|
});
|
|
366
390
|
return state;
|
|
@@ -380,7 +404,7 @@ function useIsFetching(filters, queryClient) {
|
|
|
380
404
|
const queryCache = solidJs.createMemo(() => client().getQueryCache());
|
|
381
405
|
const [fetches, setFetches] = solidJs.createSignal(
|
|
382
406
|
solidJs.untrack(() => client().isFetching(filters?.())),
|
|
383
|
-
{
|
|
407
|
+
{ ownedWrite: true }
|
|
384
408
|
);
|
|
385
409
|
const unsubscribe = solidJs.untrack(
|
|
386
410
|
() => queryCache().subscribe(() => {
|
|
@@ -405,7 +429,7 @@ function useIsMutating(filters, queryClient) {
|
|
|
405
429
|
const mutationCache = solidJs.createMemo(() => client().getMutationCache());
|
|
406
430
|
const [mutations, setMutations] = solidJs.createSignal(
|
|
407
431
|
solidJs.untrack(() => client().isMutating(filters?.())),
|
|
408
|
-
{
|
|
432
|
+
{ ownedWrite: true }
|
|
409
433
|
);
|
|
410
434
|
const unsubscribe = solidJs.untrack(
|
|
411
435
|
() => mutationCache().subscribe((_result) => {
|
|
@@ -425,7 +449,7 @@ function useMutationState(options = () => ({}), queryClient) {
|
|
|
425
449
|
const mutationCache = solidJs.createMemo(() => client().getMutationCache());
|
|
426
450
|
const [result, setResult] = solidJs.createSignal(
|
|
427
451
|
solidJs.untrack(() => getResult(mutationCache(), options())),
|
|
428
|
-
{
|
|
452
|
+
{ ownedWrite: true }
|
|
429
453
|
);
|
|
430
454
|
const unsubscribe = solidJs.untrack(
|
|
431
455
|
() => mutationCache().subscribe(() => {
|
package/build/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MutationObserver, shouldThrowError, QueriesObserver, QueryClient as QueryClient$1, replaceEqualDeep, noop, notifyManager, QueryObserver, InfiniteQueryObserver } from '@tanstack/query-core';
|
|
2
2
|
export * from '@tanstack/query-core';
|
|
3
|
-
import { createContext, useContext, onCleanup, createMemo, untrack, createRenderEffect, createStore, merge, createEffect, reconcile, createSignal, isPending, refresh, snapshot } from 'solid-js';
|
|
3
|
+
import { createContext, useContext, onCleanup, createMemo, untrack, createRenderEffect, createStore, merge, createEffect, runWithOwner, reconcile, createSignal, isPending, refresh, snapshot } from 'solid-js';
|
|
4
4
|
import { createComponent } from '@solidjs/web';
|
|
5
5
|
|
|
6
6
|
// src/useQuery.ts
|
|
@@ -83,10 +83,10 @@ var hydratableObserverResult = (query, result) => {
|
|
|
83
83
|
return obj;
|
|
84
84
|
};
|
|
85
85
|
function useBaseQuery(options, Observer, queryClient) {
|
|
86
|
-
const client =
|
|
86
|
+
const [client] = createSignal(() => useQueryClient(queryClient?.()));
|
|
87
87
|
const isRestoring = useIsRestoring();
|
|
88
88
|
let unsubscribeQueued = false;
|
|
89
|
-
const defaultedOptions =
|
|
89
|
+
const [defaultedOptions] = createSignal(() => {
|
|
90
90
|
const defaultOptions = client().defaultQueryOptions(options());
|
|
91
91
|
defaultOptions._optimisticResults = isRestoring() ? "isRestoring" : "optimistic";
|
|
92
92
|
defaultOptions.structuralSharing = false;
|
|
@@ -98,11 +98,11 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
98
98
|
return defaultOptions;
|
|
99
99
|
});
|
|
100
100
|
const observer = untrack(() => new Observer(client(), defaultedOptions()));
|
|
101
|
-
const trackedDefaultedOptions =
|
|
101
|
+
const [trackedDefaultedOptions] = createSignal(() => defaultedOptions());
|
|
102
102
|
createRenderEffect(
|
|
103
103
|
() => trackedDefaultedOptions(),
|
|
104
104
|
(opts) => {
|
|
105
|
-
observer.setOptions(opts);
|
|
105
|
+
runWithOwner(null, () => observer.setOptions(opts));
|
|
106
106
|
}
|
|
107
107
|
);
|
|
108
108
|
let observerResult = untrack(
|
|
@@ -136,8 +136,8 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
136
136
|
return observer.subscribe((result) => {
|
|
137
137
|
const previousResult = observerResult;
|
|
138
138
|
observerResult = result;
|
|
139
|
-
|
|
140
|
-
|
|
139
|
+
runWithOwner(null, () => {
|
|
140
|
+
setStateWithReconciliation(result);
|
|
141
141
|
if (unsubscribe && !disposed && (previousResult.isLoading !== result.isLoading || previousResult.isError !== result.isError)) {
|
|
142
142
|
try {
|
|
143
143
|
refresh(queryResource);
|
|
@@ -163,41 +163,58 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
163
163
|
let unsubscribe = null;
|
|
164
164
|
let disposed = false;
|
|
165
165
|
let resolver = null;
|
|
166
|
-
const queryResource =
|
|
167
|
-
()
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
166
|
+
const [queryResource] = createSignal(() => {
|
|
167
|
+
const opts = trackedDefaultedOptions();
|
|
168
|
+
const restoring = isRestoring();
|
|
169
|
+
if (isServer) {
|
|
170
|
+
const cached = observer.getOptimisticResult(opts);
|
|
171
|
+
if (!cached.isLoading) {
|
|
172
|
+
observerResult = cached;
|
|
173
|
+
runWithOwner(null, () => {
|
|
174
|
+
setStateWithReconciliation(cached);
|
|
175
|
+
});
|
|
176
|
+
return hydratableObserverResult(
|
|
177
|
+
observer.getCurrentQuery(),
|
|
178
|
+
cached
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return new Promise((resolve, reject) => {
|
|
183
|
+
resolver = resolve;
|
|
184
|
+
if (isServer) {
|
|
185
|
+
unsubscribe = createServerSubscriber((data) => {
|
|
186
|
+
resolve(data);
|
|
187
|
+
}, reject);
|
|
188
|
+
} else if (!unsubscribe && !restoring) {
|
|
189
|
+
unsubscribe = createClientSubscriber();
|
|
190
|
+
}
|
|
191
|
+
const currentResult = observer.getOptimisticResult(opts);
|
|
192
|
+
observerResult = currentResult;
|
|
193
|
+
runWithOwner(null, () => {
|
|
181
194
|
if (currentResult.isError && !currentResult.isFetching && !restoring && shouldThrowError(opts.throwOnError, [
|
|
182
195
|
currentResult.error,
|
|
183
196
|
observer.getCurrentQuery()
|
|
184
197
|
])) {
|
|
185
198
|
setStateWithReconciliation(currentResult);
|
|
186
|
-
|
|
199
|
+
reject(currentResult.error);
|
|
200
|
+
return;
|
|
187
201
|
}
|
|
188
|
-
|
|
189
|
-
resolver = null;
|
|
190
|
-
setStateWithReconciliation(currentResult);
|
|
191
|
-
return resolve(
|
|
192
|
-
hydratableObserverResult(observer.getCurrentQuery(), currentResult)
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
queueMicrotask(() => setStateWithReconciliation(currentResult));
|
|
202
|
+
setStateWithReconciliation(currentResult);
|
|
196
203
|
});
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
204
|
+
if (currentResult.isError && !currentResult.isFetching && !restoring && shouldThrowError(opts.throwOnError, [
|
|
205
|
+
currentResult.error,
|
|
206
|
+
observer.getCurrentQuery()
|
|
207
|
+
])) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (!currentResult.isLoading) {
|
|
211
|
+
resolver = null;
|
|
212
|
+
return resolve(
|
|
213
|
+
hydratableObserverResult(observer.getCurrentQuery(), currentResult)
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
});
|
|
201
218
|
onCleanup(() => {
|
|
202
219
|
disposed = true;
|
|
203
220
|
if (isServer && isPending(queryResource)) {
|
|
@@ -226,6 +243,9 @@ function useBaseQuery(options, Observer, queryClient) {
|
|
|
226
243
|
if (typeof prop === "symbol") {
|
|
227
244
|
return Reflect.get(target, prop, receiver);
|
|
228
245
|
}
|
|
246
|
+
if (isServer) {
|
|
247
|
+
queryResource();
|
|
248
|
+
}
|
|
229
249
|
if (errorPassthroughProps.has(prop)) {
|
|
230
250
|
return Reflect.get(target, prop, receiver);
|
|
231
251
|
}
|
|
@@ -335,14 +355,16 @@ function useQueries(queriesOptions, queryClient) {
|
|
|
335
355
|
() => {
|
|
336
356
|
if (!isRestoring()) {
|
|
337
357
|
unsubscribe = observer.subscribe((result) => {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
358
|
+
runWithOwner(null, () => {
|
|
359
|
+
setState(
|
|
360
|
+
reconcile(
|
|
361
|
+
[...result],
|
|
362
|
+
// Use a key function that returns undefined so reconcile
|
|
363
|
+
// uses positional matching and recursively updates nested properties
|
|
364
|
+
() => void 0
|
|
365
|
+
)
|
|
366
|
+
);
|
|
367
|
+
});
|
|
346
368
|
});
|
|
347
369
|
}
|
|
348
370
|
},
|
|
@@ -354,12 +376,14 @@ function useQueries(queriesOptions, queryClient) {
|
|
|
354
376
|
});
|
|
355
377
|
createMemo(() => {
|
|
356
378
|
const queries = defaultedQueries();
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
379
|
+
runWithOwner(null, () => {
|
|
380
|
+
observer.setQueries(
|
|
381
|
+
queries,
|
|
382
|
+
queriesOptions().combine ? {
|
|
383
|
+
combine: queriesOptions().combine
|
|
384
|
+
} : void 0
|
|
385
|
+
);
|
|
386
|
+
});
|
|
363
387
|
return queries;
|
|
364
388
|
});
|
|
365
389
|
return state;
|
|
@@ -379,7 +403,7 @@ function useIsFetching(filters, queryClient) {
|
|
|
379
403
|
const queryCache = createMemo(() => client().getQueryCache());
|
|
380
404
|
const [fetches, setFetches] = createSignal(
|
|
381
405
|
untrack(() => client().isFetching(filters?.())),
|
|
382
|
-
{
|
|
406
|
+
{ ownedWrite: true }
|
|
383
407
|
);
|
|
384
408
|
const unsubscribe = untrack(
|
|
385
409
|
() => queryCache().subscribe(() => {
|
|
@@ -404,7 +428,7 @@ function useIsMutating(filters, queryClient) {
|
|
|
404
428
|
const mutationCache = createMemo(() => client().getMutationCache());
|
|
405
429
|
const [mutations, setMutations] = createSignal(
|
|
406
430
|
untrack(() => client().isMutating(filters?.())),
|
|
407
|
-
{
|
|
431
|
+
{ ownedWrite: true }
|
|
408
432
|
);
|
|
409
433
|
const unsubscribe = untrack(
|
|
410
434
|
() => mutationCache().subscribe((_result) => {
|
|
@@ -424,7 +448,7 @@ function useMutationState(options = () => ({}), queryClient) {
|
|
|
424
448
|
const mutationCache = createMemo(() => client().getMutationCache());
|
|
425
449
|
const [result, setResult] = createSignal(
|
|
426
450
|
untrack(() => getResult(mutationCache(), options())),
|
|
427
|
-
{
|
|
451
|
+
{ ownedWrite: true }
|
|
428
452
|
);
|
|
429
453
|
const unsubscribe = untrack(
|
|
430
454
|
() => mutationCache().subscribe(() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/solid-query",
|
|
3
|
-
"version": "6.0.0-beta.
|
|
3
|
+
"version": "6.0.0-beta.4",
|
|
4
4
|
"description": "Primitives for managing, caching and syncing asynchronous and remote data in Solid",
|
|
5
5
|
"author": "tannerlinsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -52,12 +52,12 @@
|
|
|
52
52
|
"@babel/core": "^7.28.0",
|
|
53
53
|
"@babel/preset-typescript": "^7.18.6",
|
|
54
54
|
"@solidjs/testing-library": "^0.8.10",
|
|
55
|
-
"@solidjs/web": "2.0.0-beta.
|
|
56
|
-
"babel-preset-solid": "2.0.0-beta.
|
|
55
|
+
"@solidjs/web": "2.0.0-beta.7",
|
|
56
|
+
"babel-preset-solid": "2.0.0-beta.7",
|
|
57
57
|
"npm-run-all2": "^5.0.0",
|
|
58
|
-
"solid-js": "2.0.0-beta.
|
|
58
|
+
"solid-js": "2.0.0-beta.7",
|
|
59
59
|
"tsup-preset-solid": "^2.2.0",
|
|
60
|
-
"vite-plugin-solid": "3.0.0-next.
|
|
60
|
+
"vite-plugin-solid": "3.0.0-next.5",
|
|
61
61
|
"@tanstack/query-test-utils": "0.0.0"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
package/src/useBaseQuery.ts
CHANGED
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
// why that happens.
|
|
4
4
|
import { notifyManager, shouldThrowError } from '@tanstack/query-core'
|
|
5
5
|
import {
|
|
6
|
-
createMemo,
|
|
7
6
|
createRenderEffect,
|
|
7
|
+
createSignal,
|
|
8
8
|
createStore,
|
|
9
9
|
isPending,
|
|
10
10
|
onCleanup,
|
|
11
11
|
reconcile,
|
|
12
12
|
refresh,
|
|
13
|
+
runWithOwner,
|
|
13
14
|
snapshot,
|
|
14
15
|
untrack,
|
|
15
16
|
} from 'solid-js'
|
|
@@ -151,7 +152,12 @@ export function useBaseQuery<
|
|
|
151
152
|
) {
|
|
152
153
|
type ResourceData = QueryObserverResult<TData, TError>
|
|
153
154
|
|
|
154
|
-
|
|
155
|
+
// Use createSignal(fn) instead of createMemo so these derived memos have
|
|
156
|
+
// _preventAutoDisposal set. Without it, a createMemo that no one reads
|
|
157
|
+
// reactively gets auto-disposed in Solid v2, which cascades and disposes
|
|
158
|
+
// the component's onCleanup, unsubscribing the observer before the fetch
|
|
159
|
+
// completes.
|
|
160
|
+
const [client] = createSignal(() => useQueryClient(queryClient?.()))
|
|
155
161
|
const isRestoring = useIsRestoring()
|
|
156
162
|
// There are times when we run a query on the server but the resource is never read
|
|
157
163
|
// This could lead to times when the queryObserver is unsubscribed before the resource has loaded
|
|
@@ -159,7 +165,7 @@ export function useBaseQuery<
|
|
|
159
165
|
// before the resource has loaded
|
|
160
166
|
let unsubscribeQueued = false
|
|
161
167
|
|
|
162
|
-
const defaultedOptions =
|
|
168
|
+
const [defaultedOptions] = createSignal(() => {
|
|
163
169
|
const defaultOptions = client().defaultQueryOptions(options())
|
|
164
170
|
defaultOptions._optimisticResults = isRestoring()
|
|
165
171
|
? 'isRestoring'
|
|
@@ -178,7 +184,7 @@ export function useBaseQuery<
|
|
|
178
184
|
const observer = untrack(() => new Observer(client(), defaultedOptions()))
|
|
179
185
|
|
|
180
186
|
// Track options reactively so the queryResource memo re-runs on change.
|
|
181
|
-
const trackedDefaultedOptions =
|
|
187
|
+
const [trackedDefaultedOptions] = createSignal(() => defaultedOptions())
|
|
182
188
|
|
|
183
189
|
// Apply options in an effect to avoid store writes inside the memo.
|
|
184
190
|
// setOptions triggers updateResult → notify → subscription → setState,
|
|
@@ -186,7 +192,11 @@ export function useBaseQuery<
|
|
|
186
192
|
createRenderEffect(
|
|
187
193
|
() => trackedDefaultedOptions(),
|
|
188
194
|
(opts) => {
|
|
189
|
-
observer.setOptions
|
|
195
|
+
// observer.setOptions synchronously invokes subscribers which write to
|
|
196
|
+
// the store. In Solid v2, signal/store writes inside an owned scope
|
|
197
|
+
// (like this render effect) throw. Escape the owner so subscriber
|
|
198
|
+
// writes don't trip the guard.
|
|
199
|
+
runWithOwner(null, () => observer.setOptions(opts))
|
|
190
200
|
},
|
|
191
201
|
)
|
|
192
202
|
|
|
@@ -231,8 +241,8 @@ export function useBaseQuery<
|
|
|
231
241
|
return observer.subscribe((result) => {
|
|
232
242
|
const previousResult = observerResult
|
|
233
243
|
observerResult = result
|
|
234
|
-
|
|
235
|
-
|
|
244
|
+
runWithOwner(null, () => {
|
|
245
|
+
setStateWithReconciliation(result)
|
|
236
246
|
if (
|
|
237
247
|
unsubscribe &&
|
|
238
248
|
!disposed &&
|
|
@@ -243,8 +253,7 @@ export function useBaseQuery<
|
|
|
243
253
|
refresh(queryResource)
|
|
244
254
|
} catch {
|
|
245
255
|
// NotReadyError is expected when refreshing a memo that returns
|
|
246
|
-
// a Promise. The Loading boundary handles this during rendering
|
|
247
|
-
// but when refresh is called from a microtask there is no boundary.
|
|
256
|
+
// a Promise. The Loading boundary handles this during rendering.
|
|
248
257
|
}
|
|
249
258
|
}
|
|
250
259
|
})
|
|
@@ -280,27 +289,59 @@ export function useBaseQuery<
|
|
|
280
289
|
but the resource is still in a loading state
|
|
281
290
|
*/
|
|
282
291
|
let resolver: ((value: ResourceData) => void) | null = null
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
292
|
+
// Use createSignal(fn) instead of createMemo so the derived memo has
|
|
293
|
+
// _preventAutoDisposal set. Without it, a createMemo that no one reads
|
|
294
|
+
// reactively gets auto-disposed in Solid v2, which would cascade-dispose
|
|
295
|
+
// the component's onCleanup and unsubscribe the observer before fetch
|
|
296
|
+
// completion.
|
|
297
|
+
const [queryResource] = createSignal<ResourceData>(() => {
|
|
298
|
+
// Read trackedDefaultedOptions to ensure this memo re-runs when options change
|
|
299
|
+
const opts = trackedDefaultedOptions()
|
|
300
|
+
// Read isRestoring unconditionally so the memo re-runs when it changes
|
|
301
|
+
const restoring = isRestoring()
|
|
302
|
+
|
|
303
|
+
if (isServer) {
|
|
304
|
+
// On retry passes (after the streaming Loading boundary awaits a
|
|
305
|
+
// pending Promise), the QueryClient cache already has the data, so
|
|
306
|
+
// `getOptimisticResult` returns a non-loading result synchronously.
|
|
307
|
+
// Returning the value directly (instead of a fresh Promise that
|
|
308
|
+
// resolves synchronously) lets Solid's `processResult` set
|
|
309
|
+
// `comp.value` directly without queueing another async settle. If we
|
|
310
|
+
// returned a new Promise on every retry, Solid's streaming Loading
|
|
311
|
+
// boundary `while (ret.p.length)` loop in `createLoadingBoundary`
|
|
312
|
+
// would never terminate, because each retry adds a new pending
|
|
313
|
+
// Promise to the boundary's tracked set even when it resolves
|
|
314
|
+
// synchronously.
|
|
315
|
+
const cached = observer.getOptimisticResult(opts)
|
|
316
|
+
if (!cached.isLoading) {
|
|
317
|
+
observerResult = cached
|
|
318
|
+
runWithOwner(null, () => {
|
|
319
|
+
setStateWithReconciliation(cached)
|
|
320
|
+
})
|
|
321
|
+
return hydratableObserverResult(
|
|
322
|
+
observer.getCurrentQuery(),
|
|
323
|
+
cached,
|
|
324
|
+
) as ResourceData
|
|
325
|
+
}
|
|
326
|
+
}
|
|
303
327
|
|
|
328
|
+
return new Promise<ResourceData>((resolve, reject) => {
|
|
329
|
+
resolver = resolve
|
|
330
|
+
if (isServer) {
|
|
331
|
+
unsubscribe = createServerSubscriber((data) => {
|
|
332
|
+
resolve(data as ResourceData)
|
|
333
|
+
}, reject)
|
|
334
|
+
} else if (!unsubscribe && !restoring) {
|
|
335
|
+
unsubscribe = createClientSubscriber()
|
|
336
|
+
}
|
|
337
|
+
// Use getOptimisticResult instead of updateResult to keep the memo
|
|
338
|
+
// free of store writes (updateResult triggers notify → setState).
|
|
339
|
+
const currentResult = observer.getOptimisticResult(opts)
|
|
340
|
+
observerResult = currentResult
|
|
341
|
+
|
|
342
|
+
// Store writes inside a memo's owned scope throw in Solid v2.
|
|
343
|
+
// Escape the owner so setState calls are allowed.
|
|
344
|
+
runWithOwner(null, () => {
|
|
304
345
|
if (
|
|
305
346
|
currentResult.isError &&
|
|
306
347
|
!currentResult.isFetching &&
|
|
@@ -311,23 +352,31 @@ export function useBaseQuery<
|
|
|
311
352
|
])
|
|
312
353
|
) {
|
|
313
354
|
setStateWithReconciliation(currentResult)
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
if (!currentResult.isLoading) {
|
|
317
|
-
resolver = null
|
|
318
|
-
setStateWithReconciliation(currentResult)
|
|
319
|
-
return resolve(
|
|
320
|
-
hydratableObserverResult(observer.getCurrentQuery(), currentResult),
|
|
321
|
-
)
|
|
355
|
+
reject(currentResult.error)
|
|
356
|
+
return
|
|
322
357
|
}
|
|
323
|
-
|
|
324
|
-
// Defer the loading-state store write so it runs outside the memo.
|
|
325
|
-
queueMicrotask(() => setStateWithReconciliation(currentResult))
|
|
358
|
+
setStateWithReconciliation(currentResult)
|
|
326
359
|
})
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
360
|
+
|
|
361
|
+
if (
|
|
362
|
+
currentResult.isError &&
|
|
363
|
+
!currentResult.isFetching &&
|
|
364
|
+
!restoring &&
|
|
365
|
+
shouldThrowError(opts.throwOnError, [
|
|
366
|
+
currentResult.error,
|
|
367
|
+
observer.getCurrentQuery(),
|
|
368
|
+
])
|
|
369
|
+
) {
|
|
370
|
+
return
|
|
371
|
+
}
|
|
372
|
+
if (!currentResult.isLoading) {
|
|
373
|
+
resolver = null
|
|
374
|
+
return resolve(
|
|
375
|
+
hydratableObserverResult(observer.getCurrentQuery(), currentResult),
|
|
376
|
+
)
|
|
377
|
+
}
|
|
378
|
+
})
|
|
379
|
+
})
|
|
331
380
|
|
|
332
381
|
onCleanup(() => {
|
|
333
382
|
disposed = true
|
|
@@ -364,6 +413,15 @@ export function useBaseQuery<
|
|
|
364
413
|
return Reflect.get(target, prop, receiver)
|
|
365
414
|
}
|
|
366
415
|
|
|
416
|
+
// On the server, force a Suspense dependency on the query resource so
|
|
417
|
+
// the per-route Loading boundary catches NotReadyError, awaits the
|
|
418
|
+
// pending Promise, and re-renders with the resolved state. Without
|
|
419
|
+
// this, JSX reads through the Proxy never subscribe to queryResource
|
|
420
|
+
// and SSR HTML reflects the initial loading state.
|
|
421
|
+
if (isServer) {
|
|
422
|
+
queryResource()
|
|
423
|
+
}
|
|
424
|
+
|
|
367
425
|
// Always pass through error-related props without throwing
|
|
368
426
|
if (errorPassthroughProps.has(prop)) {
|
|
369
427
|
return Reflect.get(target, prop, receiver)
|
package/src/useIsFetching.ts
CHANGED
package/src/useIsMutating.ts
CHANGED
package/src/useMutationState.ts
CHANGED
package/src/useQueries.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
merge,
|
|
7
7
|
onCleanup,
|
|
8
8
|
reconcile,
|
|
9
|
+
runWithOwner,
|
|
9
10
|
untrack,
|
|
10
11
|
} from 'solid-js'
|
|
11
12
|
import { useQueryClient } from './QueryClientProvider'
|
|
@@ -244,14 +245,16 @@ export function useQueries<
|
|
|
244
245
|
() => {
|
|
245
246
|
if (!isRestoring()) {
|
|
246
247
|
unsubscribe = observer.subscribe((result) => {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
248
|
+
runWithOwner(null, () => {
|
|
249
|
+
setState(
|
|
250
|
+
reconcile(
|
|
251
|
+
[...result] as Array<QueryObserverResult>,
|
|
252
|
+
// Use a key function that returns undefined so reconcile
|
|
253
|
+
// uses positional matching and recursively updates nested properties
|
|
254
|
+
() => undefined,
|
|
255
|
+
),
|
|
256
|
+
)
|
|
257
|
+
})
|
|
255
258
|
})
|
|
256
259
|
}
|
|
257
260
|
},
|
|
@@ -265,14 +268,16 @@ export function useQueries<
|
|
|
265
268
|
// Update observer queries when options change reactively
|
|
266
269
|
const trackedDefaultedQueries = createMemo(() => {
|
|
267
270
|
const queries = defaultedQueries()
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
271
|
+
runWithOwner(null, () => {
|
|
272
|
+
observer.setQueries(
|
|
273
|
+
queries,
|
|
274
|
+
queriesOptions().combine
|
|
275
|
+
? ({
|
|
276
|
+
combine: queriesOptions().combine,
|
|
277
|
+
} as QueriesObserverOptions<TCombinedResult>)
|
|
278
|
+
: undefined,
|
|
279
|
+
)
|
|
280
|
+
})
|
|
276
281
|
return queries
|
|
277
282
|
})
|
|
278
283
|
|