tanstack-url-state 0.2.0 → 0.2.1
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/README.md +1 -1
- package/dist/use-search-state.js +17 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ function SettingsRoute() {
|
|
|
44
44
|
- **Optimistic:** every hook reading a key sees the new value at once, before the URL changes.
|
|
45
45
|
- **Batched:** updates in the same tick (or inside a `debounce` window) become one navigation.
|
|
46
46
|
- **Removal:** `null`, `undefined`, `""` and `[]` remove the key, which then reads as its default.
|
|
47
|
-
- **Setters return a promise** that resolves once the URL holds the update.
|
|
47
|
+
- **Setters return a promise** that resolves once the URL holds the update, or rejects with the router's error if the navigation fails (the state then reads the URL again).
|
|
48
48
|
|
|
49
49
|
Options, per hook or per call:
|
|
50
50
|
|
package/dist/use-search-state.js
CHANGED
|
@@ -7,7 +7,7 @@ let pending = EMPTY;
|
|
|
7
7
|
let queued = null;
|
|
8
8
|
let timer;
|
|
9
9
|
let nextFlush = null;
|
|
10
|
-
let
|
|
10
|
+
let settleFlush;
|
|
11
11
|
const listeners = new Set();
|
|
12
12
|
const subscribe = (listener) => {
|
|
13
13
|
listeners.add(listener);
|
|
@@ -21,13 +21,15 @@ const emit = () => {
|
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
23
|
const isEmpty = (value) => value === null || value === undefined || value === "" || (Array.isArray(value) && value.length === 0);
|
|
24
|
+
// Runs from a timer, so it never throws: a failed navigation rejects the setters' promise instead.
|
|
24
25
|
async function flush() {
|
|
25
26
|
timer = undefined;
|
|
26
27
|
const sent = pending;
|
|
27
28
|
const job = queued;
|
|
28
|
-
const
|
|
29
|
+
const settle = settleFlush;
|
|
29
30
|
queued = null;
|
|
30
31
|
nextFlush = null;
|
|
32
|
+
let failure;
|
|
31
33
|
try {
|
|
32
34
|
if (job) {
|
|
33
35
|
const patch = Object.fromEntries(Object.entries(sent).map(([key, value]) => [key, isEmpty(value) ? undefined : value]));
|
|
@@ -39,12 +41,21 @@ async function flush() {
|
|
|
39
41
|
});
|
|
40
42
|
}
|
|
41
43
|
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
failure = { error };
|
|
46
|
+
}
|
|
42
47
|
finally {
|
|
43
|
-
// The URL now owns what was sent
|
|
48
|
+
// The URL now owns what was sent (or kept its old values if navigating failed);
|
|
49
|
+
// keep only values set again while navigating.
|
|
44
50
|
const rest = Object.fromEntries(Object.entries(pending).filter(([key, value]) => sent[key] !== value));
|
|
45
51
|
pending = Object.keys(rest).length > 0 ? rest : EMPTY;
|
|
46
52
|
emit();
|
|
47
|
-
|
|
53
|
+
if (failure) {
|
|
54
|
+
settle?.reject(failure.error);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
settle?.resolve();
|
|
58
|
+
}
|
|
48
59
|
}
|
|
49
60
|
}
|
|
50
61
|
function enqueue(router, patch, options) {
|
|
@@ -54,8 +65,8 @@ function enqueue(router, patch, options) {
|
|
|
54
65
|
push: queued?.push === true || options.history === "push",
|
|
55
66
|
scroll: queued?.scroll === true || options.scroll === true,
|
|
56
67
|
};
|
|
57
|
-
nextFlush ??= new Promise((resolve) => {
|
|
58
|
-
|
|
68
|
+
nextFlush ??= new Promise((resolve, reject) => {
|
|
69
|
+
settleFlush = { resolve, reject };
|
|
59
70
|
});
|
|
60
71
|
emit();
|
|
61
72
|
clearTimeout(timer);
|