@tanstack/solid-query 6.0.0-rc.3 → 6.0.0-rc.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/_tsup-dts-rollup.d.cts +5 -6
- package/build/_tsup-dts-rollup.d.ts +5 -6
- package/build/dev.cjs +25 -5
- package/build/dev.js +25 -5
- package/build/index.cjs +25 -5
- package/build/index.js +25 -5
- package/package.json +1 -1
- package/src/QueryClientProvider.tsx +45 -17
- package/src/useBaseQuery.ts +42 -1
|
@@ -321,12 +321,11 @@ export { FetchStatus }
|
|
|
321
321
|
*
|
|
322
322
|
* A mutation can additionally declare its invalidation SCOPE with
|
|
323
323
|
* `X-Revalidate` keys (the `revalidate` option of Solid's `reload`/
|
|
324
|
-
* `redirect` response helpers). The payload covers the slice of
|
|
325
|
-
* the server could recompute; whatever a declared key matches
|
|
326
|
-
* swept client-side (see the consumer below).
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
* present, rather than skipping the source.
|
|
324
|
+
* `redirect`/`respond` response helpers). The payload covers the slice of
|
|
325
|
+
* that scope the server could recompute; whatever a declared key matches
|
|
326
|
+
* beyond it is swept client-side (see the consumer below). The transport
|
|
327
|
+
* delivers a response carrying keys to the consumer whether or not the
|
|
328
|
+
* collector contributed a slice — with no slice, the whole scope is swept.
|
|
330
329
|
*/
|
|
331
330
|
declare const FLIGHT_DATA_SOURCE = "sq";
|
|
332
331
|
export { FLIGHT_DATA_SOURCE }
|
|
@@ -321,12 +321,11 @@ export { FetchStatus }
|
|
|
321
321
|
*
|
|
322
322
|
* A mutation can additionally declare its invalidation SCOPE with
|
|
323
323
|
* `X-Revalidate` keys (the `revalidate` option of Solid's `reload`/
|
|
324
|
-
* `redirect` response helpers). The payload covers the slice of
|
|
325
|
-
* the server could recompute; whatever a declared key matches
|
|
326
|
-
* swept client-side (see the consumer below).
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
* present, rather than skipping the source.
|
|
324
|
+
* `redirect`/`respond` response helpers). The payload covers the slice of
|
|
325
|
+
* that scope the server could recompute; whatever a declared key matches
|
|
326
|
+
* beyond it is swept client-side (see the consumer below). The transport
|
|
327
|
+
* delivers a response carrying keys to the consumer whether or not the
|
|
328
|
+
* collector contributed a slice — with no slice, the whole scope is swept.
|
|
330
329
|
*/
|
|
331
330
|
declare const FLIGHT_DATA_SOURCE = "sq";
|
|
332
331
|
export { FLIGHT_DATA_SOURCE }
|
package/build/dev.cjs
CHANGED
|
@@ -14,14 +14,24 @@ exports.QueryClient = class QueryClient extends queryCore.QueryClient {
|
|
|
14
14
|
var isServer = typeof window === "undefined";
|
|
15
15
|
var HYDRATION_KEY_PREFIX = "sq:";
|
|
16
16
|
exports.FLIGHT_DATA_SOURCE = "sq";
|
|
17
|
+
var REVALIDATE_ALL = "*";
|
|
17
18
|
function sweepRevalidatedQueries(client, payload, response) {
|
|
18
|
-
const
|
|
19
|
-
if (
|
|
20
|
-
const covered = new Set(payload
|
|
19
|
+
const declared = response.headers.get(web.REVALIDATE_HEADER);
|
|
20
|
+
if (declared === null) return;
|
|
21
|
+
const covered = new Set(payload?.queries.map((query) => query.queryHash) ?? []);
|
|
22
|
+
const uncovered = (query) => !covered.has(query.queryHash);
|
|
23
|
+
const keys = declared.split(",");
|
|
24
|
+
if (keys.includes(REVALIDATE_ALL)) {
|
|
25
|
+
client.invalidateQueries({
|
|
26
|
+
predicate: uncovered
|
|
27
|
+
}).catch(() => void 0);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
21
30
|
for (const key of keys) {
|
|
31
|
+
if (!key) continue;
|
|
22
32
|
client.invalidateQueries({
|
|
23
33
|
queryKey: [key],
|
|
24
|
-
predicate:
|
|
34
|
+
predicate: uncovered
|
|
25
35
|
}).catch(() => void 0);
|
|
26
36
|
}
|
|
27
37
|
}
|
|
@@ -146,6 +156,7 @@ function useBaseQueryLayer(options, Observer, queryClient) {
|
|
|
146
156
|
let disposed = false;
|
|
147
157
|
let shouldAttach = false;
|
|
148
158
|
let activeClient = solidJs.untrack(client);
|
|
159
|
+
let lastQuery;
|
|
149
160
|
const attach = () => {
|
|
150
161
|
if (!disposed && !observerSub && !solidJs.untrack(isRestoring)) {
|
|
151
162
|
shouldAttach = true;
|
|
@@ -155,6 +166,7 @@ function useBaseQueryLayer(options, Observer, queryClient) {
|
|
|
155
166
|
const syncClient = (c) => {
|
|
156
167
|
if (isServer2 || c === activeClient) return;
|
|
157
168
|
activeClient = c;
|
|
169
|
+
lastQuery = void 0;
|
|
158
170
|
cacheSub?.();
|
|
159
171
|
cacheSub = c.getQueryCache().subscribe(onCacheEvent);
|
|
160
172
|
observerSub?.();
|
|
@@ -246,7 +258,14 @@ function useBaseQueryLayer(options, Observer, queryClient) {
|
|
|
246
258
|
version();
|
|
247
259
|
const c = client();
|
|
248
260
|
syncClient(c);
|
|
249
|
-
|
|
261
|
+
const cache = c.getQueryCache();
|
|
262
|
+
const opts = defaultedOptions();
|
|
263
|
+
const existing = cache.get(
|
|
264
|
+
opts.queryHash
|
|
265
|
+
);
|
|
266
|
+
if (existing) return lastQuery = existing;
|
|
267
|
+
if (lastQuery?.queryHash === opts.queryHash) return lastQuery;
|
|
268
|
+
return lastQuery = cache.build(c, opts);
|
|
250
269
|
};
|
|
251
270
|
const isEnabled = () => {
|
|
252
271
|
const opts = defaultedOptions();
|
|
@@ -305,6 +324,7 @@ function useBaseQueryLayer(options, Observer, queryClient) {
|
|
|
305
324
|
if (!isServer2) observer.setOptions(opts);
|
|
306
325
|
return chainOnce(q.fetch(opts), select, wrap);
|
|
307
326
|
}
|
|
327
|
+
if (isServer2) return { value: void 0 };
|
|
308
328
|
return NEVER;
|
|
309
329
|
};
|
|
310
330
|
const dataStore = solidJs.createProjection(
|
package/build/dev.js
CHANGED
|
@@ -13,14 +13,24 @@ var QueryClient = class extends QueryClient$1 {
|
|
|
13
13
|
var isServer = typeof window === "undefined";
|
|
14
14
|
var HYDRATION_KEY_PREFIX = "sq:";
|
|
15
15
|
var FLIGHT_DATA_SOURCE = "sq";
|
|
16
|
+
var REVALIDATE_ALL = "*";
|
|
16
17
|
function sweepRevalidatedQueries(client, payload, response) {
|
|
17
|
-
const
|
|
18
|
-
if (
|
|
19
|
-
const covered = new Set(payload
|
|
18
|
+
const declared = response.headers.get(REVALIDATE_HEADER);
|
|
19
|
+
if (declared === null) return;
|
|
20
|
+
const covered = new Set(payload?.queries.map((query) => query.queryHash) ?? []);
|
|
21
|
+
const uncovered = (query) => !covered.has(query.queryHash);
|
|
22
|
+
const keys = declared.split(",");
|
|
23
|
+
if (keys.includes(REVALIDATE_ALL)) {
|
|
24
|
+
client.invalidateQueries({
|
|
25
|
+
predicate: uncovered
|
|
26
|
+
}).catch(() => void 0);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
20
29
|
for (const key of keys) {
|
|
30
|
+
if (!key) continue;
|
|
21
31
|
client.invalidateQueries({
|
|
22
32
|
queryKey: [key],
|
|
23
|
-
predicate:
|
|
33
|
+
predicate: uncovered
|
|
24
34
|
}).catch(() => void 0);
|
|
25
35
|
}
|
|
26
36
|
}
|
|
@@ -145,6 +155,7 @@ function useBaseQueryLayer(options, Observer, queryClient) {
|
|
|
145
155
|
let disposed = false;
|
|
146
156
|
let shouldAttach = false;
|
|
147
157
|
let activeClient = untrack(client);
|
|
158
|
+
let lastQuery;
|
|
148
159
|
const attach = () => {
|
|
149
160
|
if (!disposed && !observerSub && !untrack(isRestoring)) {
|
|
150
161
|
shouldAttach = true;
|
|
@@ -154,6 +165,7 @@ function useBaseQueryLayer(options, Observer, queryClient) {
|
|
|
154
165
|
const syncClient = (c) => {
|
|
155
166
|
if (isServer2 || c === activeClient) return;
|
|
156
167
|
activeClient = c;
|
|
168
|
+
lastQuery = void 0;
|
|
157
169
|
cacheSub?.();
|
|
158
170
|
cacheSub = c.getQueryCache().subscribe(onCacheEvent);
|
|
159
171
|
observerSub?.();
|
|
@@ -245,7 +257,14 @@ function useBaseQueryLayer(options, Observer, queryClient) {
|
|
|
245
257
|
version();
|
|
246
258
|
const c = client();
|
|
247
259
|
syncClient(c);
|
|
248
|
-
|
|
260
|
+
const cache = c.getQueryCache();
|
|
261
|
+
const opts = defaultedOptions();
|
|
262
|
+
const existing = cache.get(
|
|
263
|
+
opts.queryHash
|
|
264
|
+
);
|
|
265
|
+
if (existing) return lastQuery = existing;
|
|
266
|
+
if (lastQuery?.queryHash === opts.queryHash) return lastQuery;
|
|
267
|
+
return lastQuery = cache.build(c, opts);
|
|
249
268
|
};
|
|
250
269
|
const isEnabled = () => {
|
|
251
270
|
const opts = defaultedOptions();
|
|
@@ -304,6 +323,7 @@ function useBaseQueryLayer(options, Observer, queryClient) {
|
|
|
304
323
|
if (!isServer2) observer.setOptions(opts);
|
|
305
324
|
return chainOnce(q.fetch(opts), select, wrap);
|
|
306
325
|
}
|
|
326
|
+
if (isServer2) return { value: void 0 };
|
|
307
327
|
return NEVER;
|
|
308
328
|
};
|
|
309
329
|
const dataStore = createProjection(
|
package/build/index.cjs
CHANGED
|
@@ -14,14 +14,24 @@ exports.QueryClient = class QueryClient extends queryCore.QueryClient {
|
|
|
14
14
|
var isServer = typeof window === "undefined";
|
|
15
15
|
var HYDRATION_KEY_PREFIX = "sq:";
|
|
16
16
|
exports.FLIGHT_DATA_SOURCE = "sq";
|
|
17
|
+
var REVALIDATE_ALL = "*";
|
|
17
18
|
function sweepRevalidatedQueries(client, payload, response) {
|
|
18
|
-
const
|
|
19
|
-
if (
|
|
20
|
-
const covered = new Set(payload
|
|
19
|
+
const declared = response.headers.get(web.REVALIDATE_HEADER);
|
|
20
|
+
if (declared === null) return;
|
|
21
|
+
const covered = new Set(payload?.queries.map((query) => query.queryHash) ?? []);
|
|
22
|
+
const uncovered = (query) => !covered.has(query.queryHash);
|
|
23
|
+
const keys = declared.split(",");
|
|
24
|
+
if (keys.includes(REVALIDATE_ALL)) {
|
|
25
|
+
client.invalidateQueries({
|
|
26
|
+
predicate: uncovered
|
|
27
|
+
}).catch(() => void 0);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
21
30
|
for (const key of keys) {
|
|
31
|
+
if (!key) continue;
|
|
22
32
|
client.invalidateQueries({
|
|
23
33
|
queryKey: [key],
|
|
24
|
-
predicate:
|
|
34
|
+
predicate: uncovered
|
|
25
35
|
}).catch(() => void 0);
|
|
26
36
|
}
|
|
27
37
|
}
|
|
@@ -146,6 +156,7 @@ function useBaseQueryLayer(options, Observer, queryClient) {
|
|
|
146
156
|
let disposed = false;
|
|
147
157
|
let shouldAttach = false;
|
|
148
158
|
let activeClient = solidJs.untrack(client);
|
|
159
|
+
let lastQuery;
|
|
149
160
|
const attach = () => {
|
|
150
161
|
if (!disposed && !observerSub && !solidJs.untrack(isRestoring)) {
|
|
151
162
|
shouldAttach = true;
|
|
@@ -155,6 +166,7 @@ function useBaseQueryLayer(options, Observer, queryClient) {
|
|
|
155
166
|
const syncClient = (c) => {
|
|
156
167
|
if (isServer2 || c === activeClient) return;
|
|
157
168
|
activeClient = c;
|
|
169
|
+
lastQuery = void 0;
|
|
158
170
|
cacheSub?.();
|
|
159
171
|
cacheSub = c.getQueryCache().subscribe(onCacheEvent);
|
|
160
172
|
observerSub?.();
|
|
@@ -246,7 +258,14 @@ function useBaseQueryLayer(options, Observer, queryClient) {
|
|
|
246
258
|
version();
|
|
247
259
|
const c = client();
|
|
248
260
|
syncClient(c);
|
|
249
|
-
|
|
261
|
+
const cache = c.getQueryCache();
|
|
262
|
+
const opts = defaultedOptions();
|
|
263
|
+
const existing = cache.get(
|
|
264
|
+
opts.queryHash
|
|
265
|
+
);
|
|
266
|
+
if (existing) return lastQuery = existing;
|
|
267
|
+
if (lastQuery?.queryHash === opts.queryHash) return lastQuery;
|
|
268
|
+
return lastQuery = cache.build(c, opts);
|
|
250
269
|
};
|
|
251
270
|
const isEnabled = () => {
|
|
252
271
|
const opts = defaultedOptions();
|
|
@@ -305,6 +324,7 @@ function useBaseQueryLayer(options, Observer, queryClient) {
|
|
|
305
324
|
if (!isServer2) observer.setOptions(opts);
|
|
306
325
|
return chainOnce(q.fetch(opts), select, wrap);
|
|
307
326
|
}
|
|
327
|
+
if (isServer2) return { value: void 0 };
|
|
308
328
|
return NEVER;
|
|
309
329
|
};
|
|
310
330
|
const dataStore = solidJs.createProjection(
|
package/build/index.js
CHANGED
|
@@ -13,14 +13,24 @@ var QueryClient = class extends QueryClient$1 {
|
|
|
13
13
|
var isServer = typeof window === "undefined";
|
|
14
14
|
var HYDRATION_KEY_PREFIX = "sq:";
|
|
15
15
|
var FLIGHT_DATA_SOURCE = "sq";
|
|
16
|
+
var REVALIDATE_ALL = "*";
|
|
16
17
|
function sweepRevalidatedQueries(client, payload, response) {
|
|
17
|
-
const
|
|
18
|
-
if (
|
|
19
|
-
const covered = new Set(payload
|
|
18
|
+
const declared = response.headers.get(REVALIDATE_HEADER);
|
|
19
|
+
if (declared === null) return;
|
|
20
|
+
const covered = new Set(payload?.queries.map((query) => query.queryHash) ?? []);
|
|
21
|
+
const uncovered = (query) => !covered.has(query.queryHash);
|
|
22
|
+
const keys = declared.split(",");
|
|
23
|
+
if (keys.includes(REVALIDATE_ALL)) {
|
|
24
|
+
client.invalidateQueries({
|
|
25
|
+
predicate: uncovered
|
|
26
|
+
}).catch(() => void 0);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
20
29
|
for (const key of keys) {
|
|
30
|
+
if (!key) continue;
|
|
21
31
|
client.invalidateQueries({
|
|
22
32
|
queryKey: [key],
|
|
23
|
-
predicate:
|
|
33
|
+
predicate: uncovered
|
|
24
34
|
}).catch(() => void 0);
|
|
25
35
|
}
|
|
26
36
|
}
|
|
@@ -145,6 +155,7 @@ function useBaseQueryLayer(options, Observer, queryClient) {
|
|
|
145
155
|
let disposed = false;
|
|
146
156
|
let shouldAttach = false;
|
|
147
157
|
let activeClient = untrack(client);
|
|
158
|
+
let lastQuery;
|
|
148
159
|
const attach = () => {
|
|
149
160
|
if (!disposed && !observerSub && !untrack(isRestoring)) {
|
|
150
161
|
shouldAttach = true;
|
|
@@ -154,6 +165,7 @@ function useBaseQueryLayer(options, Observer, queryClient) {
|
|
|
154
165
|
const syncClient = (c) => {
|
|
155
166
|
if (isServer2 || c === activeClient) return;
|
|
156
167
|
activeClient = c;
|
|
168
|
+
lastQuery = void 0;
|
|
157
169
|
cacheSub?.();
|
|
158
170
|
cacheSub = c.getQueryCache().subscribe(onCacheEvent);
|
|
159
171
|
observerSub?.();
|
|
@@ -245,7 +257,14 @@ function useBaseQueryLayer(options, Observer, queryClient) {
|
|
|
245
257
|
version();
|
|
246
258
|
const c = client();
|
|
247
259
|
syncClient(c);
|
|
248
|
-
|
|
260
|
+
const cache = c.getQueryCache();
|
|
261
|
+
const opts = defaultedOptions();
|
|
262
|
+
const existing = cache.get(
|
|
263
|
+
opts.queryHash
|
|
264
|
+
);
|
|
265
|
+
if (existing) return lastQuery = existing;
|
|
266
|
+
if (lastQuery?.queryHash === opts.queryHash) return lastQuery;
|
|
267
|
+
return lastQuery = cache.build(c, opts);
|
|
249
268
|
};
|
|
250
269
|
const isEnabled = () => {
|
|
251
270
|
const opts = defaultedOptions();
|
|
@@ -304,6 +323,7 @@ function useBaseQueryLayer(options, Observer, queryClient) {
|
|
|
304
323
|
if (!isServer2) observer.setOptions(opts);
|
|
305
324
|
return chainOnce(q.fetch(opts), select, wrap);
|
|
306
325
|
}
|
|
326
|
+
if (isServer2) return { value: void 0 };
|
|
307
327
|
return NEVER;
|
|
308
328
|
};
|
|
309
329
|
const dataStore = createProjection(
|
package/package.json
CHANGED
|
@@ -39,15 +39,21 @@ export const HYDRATION_KEY_PREFIX = 'sq:'
|
|
|
39
39
|
*
|
|
40
40
|
* A mutation can additionally declare its invalidation SCOPE with
|
|
41
41
|
* `X-Revalidate` keys (the `revalidate` option of Solid's `reload`/
|
|
42
|
-
* `redirect` response helpers). The payload covers the slice of
|
|
43
|
-
* the server could recompute; whatever a declared key matches
|
|
44
|
-
* swept client-side (see the consumer below).
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* present, rather than skipping the source.
|
|
42
|
+
* `redirect`/`respond` response helpers). The payload covers the slice of
|
|
43
|
+
* that scope the server could recompute; whatever a declared key matches
|
|
44
|
+
* beyond it is swept client-side (see the consumer below). The transport
|
|
45
|
+
* delivers a response carrying keys to the consumer whether or not the
|
|
46
|
+
* collector contributed a slice — with no slice, the whole scope is swept.
|
|
48
47
|
*/
|
|
49
48
|
export const FLIGHT_DATA_SOURCE = 'sq'
|
|
50
49
|
|
|
50
|
+
/**
|
|
51
|
+
* The reserved `X-Revalidate` key meaning every entry: `revalidate: '*'`
|
|
52
|
+
* on Solid's response helpers. Named so a host that keys its cache
|
|
53
|
+
* differently still reads the same spelling as "all".
|
|
54
|
+
*/
|
|
55
|
+
const REVALIDATE_ALL = '*'
|
|
56
|
+
|
|
51
57
|
/**
|
|
52
58
|
* The client half of key-scoped invalidation. A mutation declares its
|
|
53
59
|
* invalidation scope with `X-Revalidate` keys; the flight payload covers
|
|
@@ -61,24 +67,44 @@ export const FLIGHT_DATA_SOURCE = 'sq'
|
|
|
61
67
|
* A key matches by queryKey prefix — `revalidate: 'users'` sweeps every
|
|
62
68
|
* query whose key begins with `'users'`. Payload-covered hashes are exempt:
|
|
63
69
|
* they hydrated with fresh data a moment ago, and refetching them would
|
|
64
|
-
* spend the round trip single flight just saved.
|
|
70
|
+
* spend the round trip single flight just saved. The payload is absent
|
|
71
|
+
* when the server folded no slice for this cache (no collector registered,
|
|
72
|
+
* a redirect leaving the app) — then nothing is covered and the declared
|
|
73
|
+
* scope is swept in full.
|
|
74
|
+
*
|
|
75
|
+
* The header's three states are three scopes. Absent: the mutation
|
|
76
|
+
* declared nothing, and this cache is left as it is — the route data the
|
|
77
|
+
* router reloads is its own business, and a response helper without
|
|
78
|
+
* `revalidate` is a host-default that Solid Router reads as "everything"
|
|
79
|
+
* but the query cache does not presume. Empty (`revalidate: []`): nothing,
|
|
80
|
+
* explicitly. The reserved key `*` (`revalidate: '*'`): every query in the
|
|
81
|
+
* cache, minus what the payload covered — the way to say "all" to any
|
|
82
|
+
* host, rather than relying on one host's default.
|
|
65
83
|
*/
|
|
66
84
|
function sweepRevalidatedQueries(
|
|
67
85
|
client: QueryClient,
|
|
68
|
-
payload: DehydratedState,
|
|
86
|
+
payload: DehydratedState | undefined,
|
|
69
87
|
response: Response,
|
|
70
88
|
): void {
|
|
71
|
-
const
|
|
72
|
-
if (
|
|
73
|
-
const covered = new Set(
|
|
89
|
+
const declared = response.headers.get(REVALIDATE_HEADER)
|
|
90
|
+
if (declared === null) return
|
|
91
|
+
const covered = new Set(
|
|
92
|
+
payload?.queries.map((query) => query.queryHash) ?? [],
|
|
93
|
+
)
|
|
94
|
+
const uncovered = (query: Query) => !covered.has(query.queryHash)
|
|
95
|
+
const keys = declared.split(',')
|
|
96
|
+
// Background refetch failures surface through the queries' own error
|
|
97
|
+
// states; an unhandled rejection here would fail the mutation instead.
|
|
98
|
+
if (keys.includes(REVALIDATE_ALL)) {
|
|
99
|
+
client.invalidateQueries({ predicate: uncovered }).catch(() => undefined)
|
|
100
|
+
return
|
|
101
|
+
}
|
|
74
102
|
for (const key of keys) {
|
|
103
|
+
// An empty key is the empty declaration's spelling, not a prefix that
|
|
104
|
+
// happens to match everything.
|
|
105
|
+
if (!key) continue
|
|
75
106
|
client
|
|
76
|
-
.invalidateQueries({
|
|
77
|
-
queryKey: [key],
|
|
78
|
-
predicate: (query) => !covered.has(query.queryHash),
|
|
79
|
-
})
|
|
80
|
-
// Background refetch failures surface through the queries' own error
|
|
81
|
-
// states; an unhandled rejection here would fail the mutation instead.
|
|
107
|
+
.invalidateQueries({ queryKey: [key], predicate: uncovered })
|
|
82
108
|
.catch(() => undefined)
|
|
83
109
|
}
|
|
84
110
|
}
|
|
@@ -208,6 +234,8 @@ export const QueryClientProvider = (
|
|
|
208
234
|
subscribeFlightData<DehydratedState>(
|
|
209
235
|
FLIGHT_DATA_SOURCE,
|
|
210
236
|
(data, context) => {
|
|
237
|
+
// `data` is undefined for a response that carried metadata but
|
|
238
|
+
// no slice for this cache; `hydrate` ignores a non-object.
|
|
211
239
|
hydrate(props.client, data)
|
|
212
240
|
// Fresh data first, then the declared-scope sweep: stale marks
|
|
213
241
|
// land synchronously, refetches run in the background — the
|
package/src/useBaseQuery.ts
CHANGED
|
@@ -216,6 +216,27 @@ export function useBaseQueryLayer<
|
|
|
216
216
|
* swap re-attaches the rebuilt observer iff its predecessor was attached. */
|
|
217
217
|
let shouldAttach = false
|
|
218
218
|
let activeClient = untrack(client)
|
|
219
|
+
/**
|
|
220
|
+
* The entry this hook last read at its current hash, and the fallback for
|
|
221
|
+
* `query()` when the cache no longer holds that hash. Removal is the case
|
|
222
|
+
* that needs it: `removeQueries()` (or `clear()`) fires 'removed' for a
|
|
223
|
+
* hash this hook is mounted on, which bumps `version` and re-runs every
|
|
224
|
+
* derived read, and a plain `build()` there would re-create the entry the
|
|
225
|
+
* caller just removed. That resurrection is not passive, since the 'added'
|
|
226
|
+
* entry also re-points the still-live observer, whose mount-fetch policy
|
|
227
|
+
* then refetches and repopulates the key, contrary to `removeQueries`
|
|
228
|
+
* being documented to remove entries instead of refetching them.
|
|
229
|
+
*
|
|
230
|
+
* The removed instance keeps its final state, so reads hold their last
|
|
231
|
+
* value until options change or a real entry returns (`setQueryData`, a
|
|
232
|
+
* refetch, a later mount). That is what the other adapters do: a React
|
|
233
|
+
* observer keeps rendering the removed query's last result while the
|
|
234
|
+
* cache stays empty.
|
|
235
|
+
*
|
|
236
|
+
* Cleared on a client swap, below: the fallback is only meaningful for the
|
|
237
|
+
* cache it was read from.
|
|
238
|
+
*/
|
|
239
|
+
let lastQuery: Query<TQueryFnData, TError, TQueryData, TQueryKey> | undefined
|
|
219
240
|
|
|
220
241
|
const attach = () => {
|
|
221
242
|
if (!disposed && !observerSub && !untrack(isRestoring)) {
|
|
@@ -236,6 +257,7 @@ export function useBaseQueryLayer<
|
|
|
236
257
|
const syncClient = (c: QueryClient) => {
|
|
237
258
|
if (isServer || c === activeClient) return
|
|
238
259
|
activeClient = c
|
|
260
|
+
lastQuery = undefined
|
|
239
261
|
cacheSub?.()
|
|
240
262
|
cacheSub = c.getQueryCache().subscribe(onCacheEvent)
|
|
241
263
|
observerSub?.()
|
|
@@ -365,7 +387,14 @@ export function useBaseQueryLayer<
|
|
|
365
387
|
version()
|
|
366
388
|
const c = client()
|
|
367
389
|
syncClient(c)
|
|
368
|
-
|
|
390
|
+
const cache = c.getQueryCache()
|
|
391
|
+
const opts = defaultedOptions()
|
|
392
|
+
const existing = cache.get<TQueryFnData, TError, TQueryData, TQueryKey>(
|
|
393
|
+
opts.queryHash,
|
|
394
|
+
)
|
|
395
|
+
if (existing) return (lastQuery = existing)
|
|
396
|
+
if (lastQuery?.queryHash === opts.queryHash) return lastQuery
|
|
397
|
+
return (lastQuery = cache.build(c, opts as any) as any)
|
|
369
398
|
}
|
|
370
399
|
|
|
371
400
|
const isEnabled = () => {
|
|
@@ -531,6 +560,18 @@ export function useBaseQueryLayer<
|
|
|
531
560
|
if (!isServer) observer.setOptions(opts as any)
|
|
532
561
|
return chainOnce(q.fetch(opts as any), select, wrap)
|
|
533
562
|
}
|
|
563
|
+
/**
|
|
564
|
+
* Disabled, with nothing cached. The three guards above are all
|
|
565
|
+
* unreachable on the server, but this one is not, and parking here has
|
|
566
|
+
* no server meaning: the render has to finish, and nothing will enable
|
|
567
|
+
* the query or write the cache before it does. So commit the idle
|
|
568
|
+
* value — 'pending' with no data IS a disabled query's settled SSR
|
|
569
|
+
* truth, which is the contract `serverMeta` already honors by not
|
|
570
|
+
* tying its read to this node while disabled, and it is the state the
|
|
571
|
+
* client hydrates to. Committed rather than passed through `wrap`:
|
|
572
|
+
* `select` must not be invoked on absent data.
|
|
573
|
+
*/
|
|
574
|
+
if (isServer) return { value: undefined as TData }
|
|
534
575
|
return NEVER
|
|
535
576
|
}
|
|
536
577
|
|