Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
164 commits
Select commit Hold shift + click to select a range
723ed06
perf(fetchium): write an entity once per streamed event, not two or t…
abedell-phantom Sep 10, 2026
2082975
Merge branch 'main' into perf/remove-redundant-entity-saves
abedell-phantom Sep 10, 2026
180cd36
cleanup comment
abedell-phantom Sep 11, 2026
25b394a
Merge branch 'main' into perf/remove-redundant-entity-saves
abedell-phantom Sep 11, 2026
cfc2582
test(fetchium): pin zero writes for a streamed event that changes not…
abedell-phantom Sep 11, 2026
a404c28
fix(fetchium): correct the comment on the skipped child save
abedell-phantom Sep 11, 2026
545c5b1
test(fetchium): pin zero child writes when a live array gains an unch…
abedell-phantom Sep 11, 2026
d2218fe
docs(fetchium): note the zero-write outcome in the changeset
abedell-phantom Sep 11, 2026
b88c349
test(fetchium): size the refetch delay to observed CI jitter, not to 10s
abedell-phantom Sep 11, 2026
0b91282
fix(fetchium): keep write-skipping consistent with the store (pre-0.6.0)
abedell-phantom Sep 14, 2026
9f24e5d
fix(fetchium): don't write event-created entities that nothing routes
abedell-phantom Sep 14, 2026
adeebde
fix(fetchium): AsyncQueryStore readers must not offer onDelete
abedell-phantom Sep 14, 2026
1818694
perf(fetchium): snapshot entities without walking their proxies (#59)
abedell-phantom Sep 11, 2026
12c58d8
perf: don't notify or persist when applied data is unchanged (#60)
abedell-phantom Sep 11, 2026
e4419a1
Merge branch 'perf/reapply-59-60' into fix/store-consistent-write-ski…
abedell-phantom Sep 29, 2026
d42041d
chore(fetchium): rewrite this change's changesets for React developers
abedell-phantom Oct 6, 2026
90f0b12
chore(fetchium): rewrite this change's changesets for React developers
abedell-phantom Oct 6, 2026
fd3a663
perf(fetchium): quiet query reactivation and focus-aware polling
abedell-phantom Oct 3, 2026
7c59b32
fix(fetchium): credit the reactivation grace only for data a subscrip…
abedell-phantom Oct 4, 2026
9984ad9
perf(fetchium): hydrate synchronously from a sync store and start the…
abedell-phantom Oct 3, 2026
0fa1c0c
Merge branch 'fix/store-consistent-write-skipping' into perf/remove-r…
abedell-phantom Sep 29, 2026
32325c3
fix(fetchium): skip a staggered reactivation refetch made redundant d…
abedell-phantom Oct 4, 2026
e28c770
chore(fetchium): rewrite this change's changesets for React developers
abedell-phantom Oct 6, 2026
6bc090b
chore(fetchium): rewrite this change's changesets for React developers
abedell-phantom Oct 6, 2026
84c80aa
perf(fetchium): microtask refetches, prefetch/retain leases, useSuspe…
abedell-phantom Oct 3, 2026
1e0b42b
perf(fetchium): skip live value notify when a reducer returns the cur…
abedell-phantom Oct 3, 2026
8ed72a8
perf(fetchium): start prefetch/retain fetches synchronously
abedell-phantom Oct 3, 2026
b053d83
fix(fetchium): do not retry 4xx client errors; add shouldRetry
abedell-phantom Oct 3, 2026
6702797
fix(fetchium): notify a live value after every reducer run again
abedell-phantom Oct 4, 2026
b8528e4
fix(fetchium): suspend on the current fetch when a suspense hold's fe…
abedell-phantom Oct 4, 2026
bc0b555
fix(fetchium): give a remount a new attempt after an abandoned suspen…
abedell-phantom Oct 4, 2026
9003c44
fix(fetchium): resubscribe a never-loaded query before refetching it
abedell-phantom Oct 4, 2026
642baa9
fix(fetchium): bound lease lifetimes and clean them up on destroy
abedell-phantom Oct 4, 2026
86577fa
fix(fetchium): retry every failed attempt by default; keep shouldRetr…
abedell-phantom Oct 5, 2026
a7fcbd3
chore(fetchium): add a changeset for the reactivation and polling opt…
abedell-phantom Oct 6, 2026
887d5f8
chore(fetchium): rewrite this change's changesets for React developers
abedell-phantom Oct 6, 2026
7f784a8
fix(fetchium): optional store hooks for acknowledged, merged and chec…
abedell-phantom Oct 6, 2026
c9b4dfe
fix(fetchium): close the snapshot, hydration and event-persistence re…
abedell-phantom Oct 6, 2026
cb4a211
perf(fetchium): skip the per-snapshot key-cache lookup and an event's…
abedell-phantom Oct 6, 2026
f67c516
perf(fetchium): take the extra store work back out of streamed events
abedell-phantom Oct 6, 2026
e68c875
perf(fetchium): stop re-running a shared entity's consumers, copying …
abedell-phantom Oct 6, 2026
e583e75
chore(fetchium): major changeset listing the behavior changes an upgr…
abedell-phantom Oct 6, 2026
4897103
fix(fetchium): keep merging an event-built entity whose events carrie…
abedell-phantom Oct 6, 2026
bbc2772
fix(fetchium): don't turn a same-task unmount or an offline switch in…
abedell-phantom Oct 6, 2026
94a754e
chore(fetchium): shorten this change's changesets for app developers
abedell-phantom Oct 6, 2026
8bf023e
fix(fetchium): fetch and store the current params when a Signal param…
abedell-phantom Oct 6, 2026
8be1a63
chore(fetchium): rewrite this change's changesets for React developers
abedell-phantom Oct 6, 2026
ca682cf
fix(fetchium): keep a lease's release aborting the fetch it started
abedell-phantom Oct 6, 2026
c724114
fix(fetchium): keep nested values reactive when they are read on thei…
abedell-phantom Oct 6, 2026
ce9ef92
test(fetchium): benchmark reads through nested value wrappers
abedell-phantom Oct 6, 2026
0523f54
fix(fetchium): keep the query context's push hook out of Object.keys
abedell-phantom Oct 6, 2026
a383a46
fix(fetchium): tolerate app context values under the new config names
abedell-phantom Oct 6, 2026
0b4f62b
fix(fetchium): stop a slow suspense retry render from refetching in a…
abedell-phantom Oct 6, 2026
15d0aa1
chore(fetchium): changeset for the config-context and suspense-hold f…
abedell-phantom Oct 6, 2026
c152d9b
fix(fetchium): close the timing gaps around kept, deferred and late f…
abedell-phantom Oct 6, 2026
68e8f9b
perf(fetchium): hand out a new wrapper for a changed nested value ins…
abedell-phantom Oct 6, 2026
cf3eb39
chore(fetchium): changeset for the round-one timing fixes
abedell-phantom Oct 6, 2026
05c5b45
fix(fetchium): settle every awaiter when destroy(), an offline restar…
abedell-phantom Oct 6, 2026
47be6a8
fix(fetchium): keep each params key's cached data under its own record
abedell-phantom Oct 6, 2026
410e006
fix(fetchium): reject an aborted topic fetch with an AbortError when …
abedell-phantom Oct 6, 2026
e9a3d08
fix(fetchium): evict a query's previous root only while the entity ma…
abedell-phantom Oct 6, 2026
d967fe8
fix(fetchium): keep a topic query pending, not rejected, when it is u…
abedell-phantom Oct 6, 2026
7b4ae1a
fix(fetchium): serve a cached query over an in-memory entity of anoth…
abedell-phantom Oct 6, 2026
9666263
perf(fetchium): merge a streamed update into a stored record without …
abedell-phantom Oct 6, 2026
4363ebd
test(fetchium): benchmark streamed updates for a typename two classes…
abedell-phantom Oct 6, 2026
5660a02
fix(fetchium): keep any query pending, not rejected, when it is unmou…
abedell-phantom Oct 6, 2026
19730ae
chore(fetchium): rewrite this change's changesets for React developers
abedell-phantom Oct 6, 2026
9ffa42b
chore(fetchium): shorten this change's changesets for app developers
abedell-phantom Oct 6, 2026
129ac41
fix(fetchium): keep another class's child references through a list r…
abedell-phantom Oct 6, 2026
8eba14e
chore(fetchium): rewrite this change's changesets for React developers
abedell-phantom Oct 6, 2026
725101c
perf(fetchium): walk only entity-holding foreign fields, and parse th…
abedell-phantom Oct 6, 2026
7a9f94a
fix(fetchium): re-read formatted fields in the snapshot fast path
abedell-phantom Oct 6, 2026
1660e65
Merge branch 'perf/reapply-59-60' into fix/store-consistent-write-ski…
abedell-phantom Oct 6, 2026
5c78478
Merge branch 'perf/remove-redundant-entity-saves' into perf/sync-hydr…
abedell-phantom Oct 6, 2026
69f0742
Merge branch 'fix/store-consistent-write-skipping' into perf/remove-r…
abedell-phantom Oct 6, 2026
15dabd0
fix(fetchium): fetch an invalidated query whatever its staleTime
abedell-phantom Oct 6, 2026
222b7d0
Merge branch 'perf/sync-hydrate-first-fetch' into perf/quiet-reactiva…
abedell-phantom Oct 6, 2026
d5b1a9c
fix(fetchium): close three gaps in the reactivation grace and stagger
abedell-phantom Oct 6, 2026
cc302e1
Merge branch 'perf/fast-delivery' into fix/perf-stack-regressions
abedell-phantom Oct 6, 2026
f8cb9ec
Merge branch 'perf/quiet-reactivation' into perf/fast-delivery
abedell-phantom Oct 6, 2026
e4c983d
Merge branch 'fix/perf-stack-regressions' into fix/stack-timing-and-r…
abedell-phantom Oct 6, 2026
170b0d2
Merge branch 'fix/stack-timing-and-reactivity' into fix/keep-cached-f…
abedell-phantom Oct 6, 2026
281e428
test(fetchium): cover the async write order of a created child and it…
abedell-phantom Oct 6, 2026
814287a
Merge branch 'fix/stack-timing-and-reactivity' into fix/keep-cached-f…
abedell-phantom Oct 6, 2026
b4df2bc
Merge branch 'fix/perf-stack-regressions' into fix/stack-timing-and-r…
abedell-phantom Oct 6, 2026
e1ddbaf
docs(fetchium): shorten the entityFieldNamesComplete description
abedell-phantom Oct 7, 2026
bb1aae2
chore(fetchium): tighten comments
abedell-phantom Oct 7, 2026
ada6ef4
chore(fetchium): tighten comments
abedell-phantom Oct 7, 2026
fcfadea
chore(fetchium): tighten comments
abedell-phantom Oct 7, 2026
19d9d68
chore(fetchium): tighten comments
abedell-phantom Oct 7, 2026
c224b20
chore(fetchium): tighten comments
abedell-phantom Oct 7, 2026
2dc709e
chore(fetchium): tighten comments
abedell-phantom Oct 7, 2026
7fca8d6
Merge branch 'perf/quiet-reactivation' into perf/fast-delivery
abedell-phantom Oct 7, 2026
140df97
Merge branch 'perf/sync-hydrate-first-fetch' into perf/quiet-reactiva…
abedell-phantom Oct 7, 2026
1572ffc
Merge branch 'fix/store-consistent-write-skipping' into perf/remove-r…
abedell-phantom Oct 7, 2026
a1c11ef
Merge branch 'perf/remove-redundant-entity-saves' into perf/sync-hydr…
abedell-phantom Oct 7, 2026
febd864
Merge branch 'perf/reapply-59-60' into fix/store-consistent-write-ski…
abedell-phantom Oct 7, 2026
b063b83
chore(fetchium): tighten comments
abedell-phantom Oct 7, 2026
6e7ef1b
chore(fetchium): tighten comments
abedell-phantom Oct 7, 2026
3213594
chore(fetchium): tighten comments
abedell-phantom Oct 7, 2026
ebab339
Merge branch 'perf/fast-delivery' into fix/perf-stack-regressions
abedell-phantom Oct 7, 2026
8bc5f20
Merge branch 'fix/perf-stack-regressions' into fix/stack-timing-and-r…
abedell-phantom Oct 7, 2026
5fb8b6f
Merge branch 'fix/stack-timing-and-reactivity' into fix/keep-cached-f…
abedell-phantom Oct 7, 2026
f412cb9
chore(fetchium): drop PR numbers from a test header
abedell-phantom Oct 7, 2026
0531c6a
Merge branch 'fix/perf-stack-regressions' into fix/stack-timing-and-r…
abedell-phantom Oct 7, 2026
e38ae01
Merge branch 'fix/stack-timing-and-reactivity' into fix/keep-cached-f…
abedell-phantom Oct 7, 2026
aa417f3
fix(fetchium): release a retain() lease when starting one of its quer…
abedell-phantom Oct 7, 2026
2aba512
Merge branch 'perf/fast-delivery' into fix/perf-stack-regressions
abedell-phantom Oct 7, 2026
99982a5
fix(fetchium): keep store bookkeeping right after a failed write or a…
abedell-phantom Oct 7, 2026
fbe4670
Merge branch 'fix/perf-stack-regressions' into fix/stack-timing-and-r…
abedell-phantom Oct 7, 2026
ae6aa5c
fix(fetchium): drop a response that arrives after destroy()
abedell-phantom Oct 7, 2026
9a2f8a1
Merge branch 'fix/stack-timing-and-reactivity' into fix/keep-cached-f…
abedell-phantom Oct 7, 2026
144b840
fix(fetchium): keep the other class's fields when a record read or wr…
abedell-phantom Oct 7, 2026
c3e458b
chore(fetchium): cut and shorten comments
abedell-phantom Oct 7, 2026
c33c1bb
chore(fetchium): cut and shorten comments
abedell-phantom Oct 7, 2026
fa11a4d
chore(fetchium): cut and shorten comments
abedell-phantom Oct 7, 2026
b40ebdc
chore(fetchium): cut and shorten comments
abedell-phantom Oct 7, 2026
a103d63
chore(fetchium): cut and shorten comments
abedell-phantom Oct 7, 2026
feeacdc
chore(fetchium): cut and shorten comments
abedell-phantom Oct 7, 2026
fe48f0d
chore(fetchium): cut and shorten comments
abedell-phantom Oct 7, 2026
d7da9e3
Merge branch 'perf/reapply-59-60' into fix/store-consistent-write-ski…
abedell-phantom Oct 7, 2026
1ad691b
Merge branch 'fix/store-consistent-write-skipping' into perf/remove-r…
abedell-phantom Oct 7, 2026
7dc0afe
Merge branch 'perf/remove-redundant-entity-saves' into perf/sync-hydr…
abedell-phantom Oct 7, 2026
aec1847
Merge branch 'perf/sync-hydrate-first-fetch' into perf/quiet-reactiva…
abedell-phantom Oct 7, 2026
10958e9
chore(fetchium): cut and shorten comments
abedell-phantom Oct 7, 2026
15a2722
Merge branch 'perf/quiet-reactivation' into perf/fast-delivery
abedell-phantom Oct 7, 2026
29afebf
Merge branch 'fix/stack-timing-and-reactivity' into fix/keep-cached-f…
abedell-phantom Oct 7, 2026
9a8fea3
Merge branch 'fix/perf-stack-regressions' into fix/stack-timing-and-r…
abedell-phantom Oct 7, 2026
d468448
Merge branch 'perf/fast-delivery' into fix/perf-stack-regressions
abedell-phantom Oct 7, 2026
ae999c3
Merge branch 'fix/stack-timing-and-reactivity' into fix/keep-cached-f…
abedell-phantom Oct 7, 2026
8d0adf6
chore(fetchium): note Infinity in the reactivationGraceMs doc
abedell-phantom Oct 7, 2026
fff1175
chore(fetchium): say what mayMissForeignFields answers
abedell-phantom Oct 7, 2026
8cccf20
fix(fetchium): keep a throwing getConfig() from stalling Signalium's …
abedell-phantom Oct 7, 2026
cb300b4
fix(fetchium): recover a query once its getConfig() stops throwing
abedell-phantom Oct 7, 2026
1d0f6d0
fix(fetchium): stop all store writes and requests after destroy()
abedell-phantom Oct 7, 2026
b384ba8
fix(fetchium): keep other class fields when an async write follows a …
abedell-phantom Oct 7, 2026
96a5200
fix(fetchium): keep event writes and store listeners safe when the st…
abedell-phantom Oct 7, 2026
1ae384d
Merge branch 'perf/fast-delivery' into fix/perf-stack-regressions
abedell-phantom Oct 7, 2026
1aa7958
Merge branch 'fix/perf-stack-regressions' into fix/stack-timing-and-r…
abedell-phantom Oct 7, 2026
c12e030
Merge branch 'fix/stack-timing-and-reactivity' into fix/keep-cached-f…
abedell-phantom Oct 7, 2026
dd60079
fix(fetchium): keep a newer abort's flag when a replaced fetch lands …
abedell-phantom Oct 7, 2026
85b4f1c
Merge branch 'fix/stack-timing-and-reactivity' into fix/keep-cached-f…
abedell-phantom Oct 7, 2026
efd435a
fix(fetchium): cancel a queued debounce when starting a fetch immedia…
abedell-phantom Oct 7, 2026
aed1986
Merge branch 'perf/sync-hydrate-first-fetch' into perf/quiet-reactiva…
abedell-phantom Oct 7, 2026
181236c
Merge branch 'perf/quiet-reactivation' into perf/fast-delivery
abedell-phantom Oct 7, 2026
27ea7d8
fix(fetchium): cancel any queued debounced run when starting a fetch …
abedell-phantom Oct 7, 2026
208a412
Merge branch 'perf/fast-delivery' into fix/perf-stack-regressions
abedell-phantom Oct 7, 2026
389386f
Merge branch 'fix/perf-stack-regressions' into fix/stack-timing-and-r…
abedell-phantom Oct 7, 2026
d9a28ff
Merge branch 'fix/stack-timing-and-reactivity' into fix/keep-cached-f…
abedell-phantom Oct 7, 2026
a0f6208
fix(fetchium): pass a mutation response's status to shouldRetry
abedell-phantom Oct 7, 2026
04a4609
fix(fetchium): refetch changed params and pending invalidations on re…
abedell-phantom Oct 7, 2026
86cd229
Merge fix for review comments into perf/quiet-reactivation
abedell-phantom Oct 7, 2026
29899c7
Merge branch 'perf/quiet-reactivation' into perf/fast-delivery
abedell-phantom Oct 7, 2026
5db8976
Merge fix for review comment into perf/fast-delivery
abedell-phantom Oct 7, 2026
1bf0674
Merge branch 'perf/fast-delivery' into fix/perf-stack-regressions
abedell-phantom Oct 7, 2026
550f149
Merge branch 'fix/perf-stack-regressions' into fix/stack-timing-and-r…
abedell-phantom Oct 7, 2026
4a17ae6
Merge branch 'fix/stack-timing-and-reactivity' into fix/keep-cached-f…
abedell-phantom Oct 7, 2026
c1fef15
perf(fetchium): warm V8's enum cache for an entity shape at registration
abedell-phantom Oct 7, 2026
d7b7bbd
Merge branch 'fix/stack-timing-and-reactivity' into fix/keep-cached-f…
abedell-phantom Oct 7, 2026
3ecb2ff
docs(fetchium): make the perf stack's docs and changesets concise
abedell-phantom Oct 7, 2026
ef70b2e
Merge branch 'docs/concise-perf-stack-74' into fix/keep-cached-first-…
abedell-phantom Oct 7, 2026
036e2bb
docs(fetchium): separate hooks from component(), and qualify abort an…
abedell-phantom Oct 8, 2026
c81f8c9
Merge branch 'docs/concise-perf-stack-74' into fix/keep-cached-first-…
abedell-phantom Oct 8, 2026
41392ec
Merge branch 'main' into fix/keep-cached-first-paint
abedell-phantom Oct 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .changeset/activation-timing-fixes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
'fetchium': patch
---

Fixed spurious errors and wrong data when a query mounts, unmounts or changes params quickly.
Fixed errors and wrong data when a query mounts, unmounts or changes params quickly.

- Unmounting and remounting a query, in the same task or mid-fetch (switching a chart timeframe and back), no longer shows an `AbortError`. The query shows its cached data, or stays pending, while it refetches. One exception: a topic query with no data that mounts and unmounts in the same task shows the `AbortError` on its next mount until its data arrives (before, it stayed pending forever).
- Changing a Signal param mid-fetch fetches the new params instead of showing the old params' response. A query whose result is not an entity now caches each params value separately; a cold start could show another params value's data.
- `QueryClient.destroy()` aborts every fetch in flight, and code awaiting one gets an `AbortError`.
- Remounting a query after an aborted fetch shows its cached data, or stays pending, instead of an `AbortError`. A topic query with no data that mounts and unmounts in the same task is the exception: it shows the `AbortError` until its data arrives, and its first awaiter rejects.
- Changing a Signal param mid-fetch fetches the new params. Each params value of a non-entity result is cached separately.
- `QueryClient.destroy()` aborts fetches in flight. Queries read afterwards reject with an `AbortError` and send no requests.
2 changes: 1 addition & 1 deletion .changeset/async-store-honors-max-count.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
'fetchium': patch
---

`AsyncQueryStore` now honors a query's `cache.maxCount`, as `SyncQueryStore` does. It used to always keep the default of 50 keys.
`AsyncQueryStore` now honors a query's `cache.maxCount` instead of always keeping 50 entries.
6 changes: 3 additions & 3 deletions .changeset/config-context-and-suspense-holds.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
'fetchium': patch
---

`useSuspenseQuery` no longer refetches in a loop when a slow retry render takes a while to reach the component. The error goes to the error boundary, and resetting the boundary retries.

Custom `QueryClientConfig` keys still reach queries as `this.context`, except the reserved option names `shouldRetry`, `reactivationGraceMs`, `reactivationStaggerMs`, `activity` and `pollResumeJitterMs`. An invalid value for one of these options is ignored instead of breaking queries.
- Fixed `useSuspenseQuery` refetching in a loop when a retry render is slow.
- A query whose `getConfig()` throws now rejects with that error instead of breaking other queries.
- `shouldRetry`, `reactivationGraceMs`, `reactivationStaggerMs`, `activity` and `pollResumeJitterMs` are reserved `QueryClientConfig` names. Other keys still reach queries as `this.context`.
4 changes: 1 addition & 3 deletions .changeset/entity-snapshot-fast-path.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,4 @@
'fetchium': patch
---

Query results rebuild faster after an update: entities whose data didn't change are not read again.

List results also keep each row's object identity when the list is inserted into or re-sorted, so memoized rows don't re-render. Development builds still re-read everything to check the result, so the speedup shows in production builds only.
Query results rebuild faster after an update in production builds, and list rows keep their identity when the list is re-sorted or inserted into.
9 changes: 3 additions & 6 deletions .changeset/fast-delivery-prefetch-retain.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
'fetchium': minor
---

New `queryClient.prefetch(Query, params, { ttl })` and `queryClient.retain(fn, { ttl })` start queries before any component reads them. A component that mounts while one is held reuses its request and renders the data on its first render if it has arrived. Both return a `release` function; `prefetch` lasts 10 seconds by default and `retain` until released.

New `useSuspenseQuery` in `fetchium/react`. It suspends only while the query has no data yet, and sends a failed first fetch to the error boundary.

- A refetch without `debounce` starts on a microtask instead of after `setTimeout(0)`.
- Reading `.value` on a pending or failed query doesn't suspend or throw. The docs said it did.
- New `queryClient.prefetch(Query, params, { ttl })` and `queryClient.retain(fn, { ttl })` start queries before a component reads them. A component that mounts meanwhile reuses the request.
- New `useSuspenseQuery` in `fetchium/react`. It suspends only while the query has no value.
- Refetches without `debounce` start on a microtask instead of after `setTimeout(0)`.
10 changes: 10 additions & 0 deletions .changeset/keep-cached-first-paint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'fetchium': patch
---

Cached data now shows on the first render when two entity classes share a typename, such as a list class and a detail class with more fields. Before, the detail query waited for the network if the list had already loaded the entity.

- Writing an entity through one class keeps the other class's fields in the store, so the detail cache survives a restart. Loading the list from the cache now also parses those fields.
- Refetching the list no longer drops entities that only the detail references, such as its nested `t.entity` field. Before, the detail kept the old value, stopped getting updates for it, and its cache failed to load after a restart. This bug was in every earlier version.
- To wipe the cache, call the new `SyncQueryStore.clear()`, not the storage's own clear (such as MMKV `clearAll()`), which can bring deleted fields back.
- Custom stores can add the new optional `QueryStore` methods `readEntity`, `getEntityFieldNames`, `addEntityFieldNames` and `entityFieldNamesComplete`. Without them nothing changes.
2 changes: 1 addition & 1 deletion .changeset/nested-value-reactivity.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
'fetchium': patch
---

Fixed memoized children (`component()` or `React.memo`) showing a stale value when given a nested value such as `token.price` as a prop. A nested `t.object`, `t.record` or live-collection value is now a new object when it changes, and keeps its identity when it doesn't.
Fixed memoized children not updating when passed a nested value such as `token.price`. Nested `t.object`, `t.record` and live-collection values are new objects when they change.
10 changes: 5 additions & 5 deletions .changeset/quiet-reactivation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
'fetchium': minor
---

New `QueryClient` options that make coming back to a screen, or to the app, quieter. All are off by default.
New `QueryClient` options, all off by default:

- `reactivationGraceMs` (also per query): a query that mounts again with data younger than this doesn't refetch. Data a live subscription kept current counts as fresh.
- `reactivationStaggerMs`: refetches from queries that mount together are spread across this window instead of all starting at once.
- `activity: { isActive(), subscribe(listener) }`: `poll()` stops while the app is inactive and resumes when it's active again. On React Native, wrap `AppState`. `pollResumeJitterMs` spreads out polls that were overdue on resume.
- Pass the topic to `TopicQueryAdapter.sendMutationEvent(event, topic)` so that topic's query counts the push as fresh data.
- `reactivationGraceMs` (also per query): skip the refetch when a query remounts with data younger than this.
- `reactivationStaggerMs`: spread the refetches of queries that remount together across this window.
- `activity` and `pollResumeJitterMs`: pause `poll()` while the app is inactive and spread overdue polls on resume.
- `TopicQueryAdapter.sendMutationEvent(event, topic)` counts the event as fresh data for that topic's query.
4 changes: 1 addition & 3 deletions .changeset/remove-redundant-entity-saves.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,4 @@
'fetchium': patch
---

Streamed updates write each changed entity to the store once instead of two or three times, and an update that changes nothing writes nothing.

A `create` event for an entity that no live collection shows is no longer written to the store, where it was never cleaned up.
Streamed updates write each changed entity once, and unchanged updates write nothing.
4 changes: 1 addition & 3 deletions .changeset/should-retry-hook.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,4 @@
'fetchium': minor
---

New optional `shouldRetry(error, attempt, status)` on `QueryClientConfig` and on a query's or mutation's `retry` config. Return `false` to stop retrying an error you know is permanent, such as a 404.

`status` is the HTTP status when it is known, and `getErrorStatus` is exported. Without the hook, retries work as before. `retry.retries` is now optional.
New `shouldRetry(error, attempt, status)` option on `QueryClientConfig` and `retry` configs. Return `false` to stop retrying, for example on a 404. `getErrorStatus` is exported and `retry.retries` is now optional.
5 changes: 1 addition & 4 deletions .changeset/skip-unchanged-entity-merges.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,4 @@
'fetchium': minor
---

A refetch, poll or streamed update that returns the same data no longer re-renders your components. `isPending` and `isFetching` still change as before.

- Values that can't be compared reliably (a `Date`, a typed array, a class instance) always count as changed.
- `t.record(...)` fields now apply updates. Previously a record field kept its old value.
A refetch, poll or streamed update with identical data no longer re-renders components. `t.record` fields now apply updates.
8 changes: 3 additions & 5 deletions .changeset/skip-write-and-snapshot-fixes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
'fetchium': patch
---

Fixed stale data in components when a second query loads entities that are already in memory, and streamed updates that were lost on restart.

- Development builds freeze query results, so mutating one (such as calling `sort()` on a list in render) throws a `TypeError`. Copy the data first, and treat production results as read-only too.
- In development, the stale-data check logs an error instead of throwing and blocking other components' updates.
- Custom stores can add the new optional `QueryStore.mergeEntity`, so an entity built from streamed updates doesn't overwrite stored fields those updates didn't include. Without it, writes work as before.
- Fixed stale data when a query loads entities already in memory, and streamed updates lost on restart.
- Development builds freeze query results. Copy data before mutating it.
- Custom stores can implement the new optional `QueryStore.mergeEntity`.
2 changes: 1 addition & 1 deletion .changeset/snapshot-union-array-members.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
'fetchium': patch
---

Fixed components not updating when an entity changes inside a union that has an array or record member, such as `t.union(t.array(t.entity(A)), t.object({ ... }))`.
Fixed components not updating when an entity changes inside a union with an array or record member.
6 changes: 2 additions & 4 deletions .changeset/store-reports-deletions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,5 @@
'fetchium': patch
---

Fixed cached queries failing to load after a restart ("the query cache may be corrupted or invalid") when a query had more than `cache.maxCount` cached params and refetched unchanged data.

- Custom stores: `QueryStore` has a new optional `onDelete(listener)`. Call the listener with every id the store deletes on its own. A store without it keeps writing every update, as before.
- A `t.array(t.entity(X))` field whose typename two entity classes share now shows an item as soon as it gains the fields `X` requires.
- Fixed cached queries failing to load after a restart when a query had more than `cache.maxCount` cached entries.
- Custom stores can implement the new optional `QueryStore.onDelete(listener)`.
5 changes: 1 addition & 4 deletions .changeset/sync-hydrate-first-fetch.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,4 @@
'fetchium': patch
---

With `SyncQueryStore`, a cached query renders its data on the first render instead of showing a loading frame first.

- The first fetch starts on a microtask instead of after `setTimeout(0)`. Tests that wait for a loading state or count renders may need updating.
- A cached entry that can't be loaded is treated as a cache miss and fetched. Previously a fresh-looking entry could leave the query pending without fetching.
With `SyncQueryStore`, cached data shows on the first render, and the first fetch starts on a microtask. A cache entry that fails to load is refetched.
2 changes: 1 addition & 1 deletion .changeset/sync-store-merge-without-read.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
'fetchium': patch
---

Faster streamed updates with `SyncQueryStore` for entities that aren't in memory, which is common when two entity classes share a typename.
Faster streamed updates with `SyncQueryStore` for entities not in memory.
27 changes: 13 additions & 14 deletions .changeset/upgrade-behavior-changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@
'fetchium': major
---

Breaking changes. Most apps need no code changes, but tests that depend on loading frames, render counts or timers may.
Most apps need no changes. Tests that depend on loading frames, render counts or timers may.

- **Results are frozen in development.** Mutating query data throws a `TypeError`; copy it first (`[...data.items].sort()`).
- **Cached data shows on the first render** with `SyncQueryStore`. Update tests that wait for a loading state or count renders.
- **Fetches start sooner.** The first fetch and refetches without `debounce` start on a microtask, not after `setTimeout(0)`; update tests that advance timers to see them.
- **Identical data doesn't re-render.** A refetch, poll or streamed update with the same data skips the render; read `isFetching` instead of counting renders.
- **Nested values change identity only when they change.** `t.object`, `t.record` and live-collection values are new objects after a change, so memoized children re-render; drop workarounds that forced it.
- **`t.record` and `t.result` fields apply updates** instead of keeping their old value.
- **Changing a Signal param mid-fetch aborts that fetch** and fetches the new params; the old response is dropped.
- **`QueryClient.destroy()` aborts fetches in flight.** Code that awaits a query during teardown gets an `AbortError`; catch it.
- **Awaiting a query can wait for a remount.** If the last component using a query unmounts before its first data arrives, `await fetchQuery(...)` waits for the next mount, `gcTime` collection or `destroy()` instead of rejecting with an `AbortError`.
- **New reserved `QueryClientConfig` names:** `shouldRetry`, `reactivationGraceMs`, `reactivationStaggerMs`, `activity` and `pollResumeJitterMs` are read as options; rename custom context values that use them.
- **`retry: {}` and `retry: { retryDelay }` now retry** like `retry: true`; use `retry: false` for no retries.
- **`AsyncQueryStore` honors `cache.maxCount`.** Check the value if you set one.
- **Custom `QueryStore`s** get new optional methods (`mergeEntity`, `onDelete`, `onPersisted`, `isSettled`, `hasQueuedDeletes`, `hasEntity`); without them nothing changes.
- Query results are frozen in development. Copy data before mutating it.
- With `SyncQueryStore`, cached data shows on the first render.
- The first fetch and refetches without `debounce` start on a microtask, not after `setTimeout(0)`.
- Identical data no longer re-renders. Check `isFetching` instead of counting renders.
- Nested `t.object`, `t.record` and live-collection values are new objects when they change.
- `t.record` and `t.result` fields apply updates.
- Changing a Signal param mid-fetch aborts that fetch.
- After `QueryClient.destroy()`, queries reject with an `AbortError` and send no requests.
- If the last reader unmounts before a query's first data, `await fetchQuery(...)` waits for the next mount, collection or `destroy()`. A topic query mounted and unmounted in the same task still rejects.
- `shouldRetry`, `reactivationGraceMs`, `reactivationStaggerMs`, `activity` and `pollResumeJitterMs` are reserved `QueryClientConfig` names.
- `retry: {}` and `retry: { retryDelay }` now retry like `retry: true`.
- `AsyncQueryStore` honors `cache.maxCount`.
Loading
Loading