Skip to content

Commit 6b89dfb

Browse files
better approach
1 parent 5218f9d commit 6b89dfb

File tree

1 file changed

+48
-74
lines changed

1 file changed

+48
-74
lines changed

src/routes/inputs/Inputs.svelte

Lines changed: 48 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,58 @@
11
<script lang="ts">
2-
import { useQuery, useConvexClient } from '$lib/client.svelte.js';
3-
import type { Doc } from '../../convex/_generated/dataModel.js';
4-
import { api } from '../../convex/_generated/api.js';
2+
import { useQuery, useConvexClient } from '$lib/client.svelte.js';
3+
import type { Doc } from '../../convex/_generated/dataModel.js';
4+
import { api } from '../../convex/_generated/api.js';
55
6-
const convex = useConvexClient();
7-
const serverNumbers = useQuery(api.numbers.get, {});
6+
const convex = useConvexClient();
7+
const serverNumbers = useQuery(api.numbers.get, {});
88
9-
let numbers = $state(serverNumbers.isLoading ? {} : { a: serverNumbers.a, b: serverNumbers.b, c: serverNumbers.c });
10-
let pendingMutations = $state(0);
11-
let lastMutationPromise: Promise<any> | null = $state(null);
12-
let hasUnsentChanges = $state(false); // Track if we have changes waiting in debounce
9+
let numbers = $state(null);
10+
// Have some changes not yet been sent?
11+
let hasUnsentChanges = $state(false);
12+
// Does delivered server state not yet reflect all local changes?
13+
let hasUnsavedChanges = $state(false);
14+
let mutationInFlight = $state(false);
1315
14-
// Stay in sync with server data only when no mutations are pending and there are now changes waiting to be sent
15-
$effect(() => {
16-
if (!serverNumbers.isLoading && serverNumbers.data &&
17-
pendingMutations === 0 && !hasUnsentChanges) {
18-
console.log('Received data from server:', {
19-
a: serverNumbers.data.a,
20-
b: serverNumbers.data.b,
21-
c: serverNumbers.data.c,
22-
});
23-
numbers.a = serverNumbers.data.a;
24-
numbers.b = serverNumbers.data.b;
25-
numbers.c = serverNumbers.data.c;
26-
}
27-
});
16+
// Initialize local state when server data first arrives
17+
$effect(() => {
18+
if (!serverNumbers.isLoading && serverNumbers.data && !numbers) {
19+
numbers = { ...serverNumbers.data };
20+
}
21+
});
2822
29-
// Queue updates and track pending mutations
30-
async function queueMutation() {
31-
if (serverNumbers.isLoading) return;
23+
// Update local state with server data
24+
$effect(() => {
25+
if (!hasUnsavedChanges && !serverNumbers.isLoading && serverNumbers.data) {
26+
numbers = { ...serverNumbers.data };
27+
}
28+
});
3229
33-
pendingMutations++;
34-
hasUnsentChanges = false;
30+
async function publishChanges() {
31+
hasUnsentChanges = true;
32+
hasUnsavedChanges = true;
33+
if (!numbers || mutationInFlight) return;
3534
36-
console.log('Updating server with', numbers, pendingMutations, 'mutations pending');
37-
const currentMutation = convex.mutation(api.numbers.update, {
38-
a: numbers.a,
39-
b: numbers.b,
40-
c: numbers.c
41-
});
35+
hasUnsentChanges = false;
36+
mutationInFlight = true
37+
await convex.mutation(api.numbers.update, numbers);
38+
mutationInFlight = false
4239
43-
lastMutationPromise = currentMutation;
40+
if (hasUnsentChanges) {
41+
publishChanges();
42+
} else {
43+
hasUnsavedChanges = false;
44+
}
45+
}
4446
45-
try {
46-
await currentMutation;
47-
console.log('saved to server');
48-
} finally {
49-
pendingMutations--;
50-
51-
// If this was the last mutation in the queue,
52-
// explicitly sync with server state
53-
if (pendingMutations === 0 && !hasUnsentChanges &&
54-
serverNumbers.data && currentMutation === lastMutationPromise) {
55-
console.log('finished persisting state to server, back to following useQuery');
56-
numbers.a = serverNumbers.data.a;
57-
numbers.b = serverNumbers.data.b;
58-
numbers.c = serverNumbers.data.c;
59-
}
60-
}
61-
}
47+
function handleNumericInput(prop, e) {
48+
numbers[prop] = e.currentTarget.valueAsNumber
49+
publishChanges();
50+
};
6251
63-
// Track changes immediately but debounce the actual mutation
64-
let updateTimeout: number | undefined;
65-
$effect(() => {
66-
if (serverNumbers.isLoading) return;
67-
68-
// reference values so this is reactive on them
69-
const currentValues = {
70-
a: numbers.a,
71-
b: numbers.b,
72-
c: numbers.c
73-
};
74-
hasUnsentChanges = true;
75-
76-
clearTimeout(updateTimeout);
77-
updateTimeout = setTimeout(queueMutation, 500) as unknown as number;
78-
79-
return () => clearTimeout(updateTimeout);
80-
});
8152
</script>
8253

8354
<div class="numbers">
84-
{#if serverNumbers.isLoading}
55+
{#if serverNumbers.isLoading || !numbers}
8556
<div>
8657
<p>Loading values...</p>
8758
</div>
@@ -91,7 +62,8 @@
9162
<input
9263
id="a"
9364
type="number"
94-
bind:value={numbers.a}
65+
oninput={(e) => handleNumericInput('a', e)}
66+
value={numbers.a}
9567
/>
9668
</div>
9769

@@ -100,7 +72,8 @@
10072
<input
10173
id="b"
10274
type="number"
103-
bind:value={numbers.b}
75+
oninput={(e) => handleNumericInput('b', e)}
76+
value={numbers.b}
10477
/>
10578
</div>
10679

@@ -109,7 +82,8 @@
10982
<input
11083
id="c"
11184
type="number"
112-
bind:value={numbers.c}
85+
oninput={(e) => handleNumericInput('c', e)}
86+
value={numbers.c}
11387
/>
11488
</div>
11589

0 commit comments

Comments
 (0)