Commit 311ab2b
fix: preserve fragment data identity across snapshot updates (#68)
* fix: preserve fragment data identity across snapshot updates
`reconcile({ key: "__id", merge: true })` only preserves identity by
walking the existing tree in place when the current store value is
wrappable. solid-js/store's `reconcile` (modifiers.ts) early-returns
the new value as-is when it isn't, so reconciling against `undefined`
silently produces a fresh top-level reference and the merge contract
goes away.
The result observer was pre-clearing `data` to `undefined` inside the
same batch that subsequently applied the reconciled snapshot, so that
contract was being defeated on every Relay update. Identity-sensitive
consumers — most prominently `<Show keyed when={data()}>` — re-mounted
their subtree on every snapshot tick, including pure field updates
such as a reaction toggle or a polled count delta. In a real fediverse
timeline (hackers.pub `/feed`, ~25 cards × multiple Kobalte primitives
per card), this dominated CPU and heap during interaction (~+10 MB/s
sustained vs. ~0 MB/s when idle on the same route).
Restructure the observer so each branch owns its full state transition
and no shared pre-clears defeat the reconcile:
- "ok" — clear `error`, set `pending` to false, reconcile `data`.
- "error" — set `data` to `undefined`, set `error`, set `pending`.
- "loading" — no case. Leave `data` / `error` / `pending` as-is for
stale-while-revalidate behaviour, matching `createLazyLoadQuery`'s
observer in the same package.
Behaviour is otherwise unchanged. Observers never saw the intermediate
pre-clear state — every mutation is inside the same `batch()` — so the
fix is invisible to anything except identity comparisons across snapshot
boundaries, which the reconcile contract is exactly there to keep
stable.
Assisted-by: Claude Code:claude-opus-4-7
* chore: clean up comments
* fix: handle loading fragment state properly
* chore: add changeset
---------
Co-authored-by: Iha Shin <me@xiniha.dev>1 parent 1bfb1a9 commit 311ab2b
2 files changed
Lines changed: 10 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
132 | 132 | | |
133 | 133 | | |
134 | 134 | | |
135 | | - | |
136 | | - | |
137 | | - | |
138 | 135 | | |
139 | 136 | | |
140 | 137 | | |
| |||
146 | 143 | | |
147 | 144 | | |
148 | 145 | | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
149 | 151 | | |
150 | 152 | | |
151 | 153 | | |
| |||
0 commit comments