[3.1.0] - 2026-07-08
Added
scopedoption onasyncChunkandpaginatedAsyncChunk— whentrue,useAsyncChunk/useInfiniteAsyncChunktransparently give each calling component its own isolated instance instead of sharing the exported chunk's state. The export syntax is unchanged — no factory function oruseStatewrapper needed at the call site.
export const searchResultsChunk = paginatedAsyncChunk(fetcher, {
pagination: { pageSize: 20, mode: "replace" },
scoped: true,
});
// Each component using searchResultsChunk now gets independent
// data/pagination/params state.Use scoped: true for parameterized or filtered data (search results, tables with independent filters, multiple simultaneous tabs) where sharing one singleton across consumers causes them to fight over setParams/nextPage/cached data. Leave the default (false) for true app-wide singletons (current user, wallet, notifications) where every consumer must observe the same state.
Only useAsyncChunk/useInfiniteAsyncChunk resolve scoped — calling methods directly on the exported chunk outside a component still operates on the one shared singleton instance.
reset(refetch?: boolean)—reset()now accepts an optional parameter (defaulttrue) controlling whether it triggers a refetch after clearing state. Passreset(false)for flows like logout, where state should clear without firing an unauthenticated request.
notificationsChunk.reset(); // clears and refetches (default)
notificationsChunk.reset(false); // clears only — no refetchFixed
reload()now resets pagination cursor and page to initial state. Previously,reload()reused whatever cursor/page was left over from the lastnextPage()call, so repeatedreload()calls (from SSE updates, login, component remounts) silently advanced through pages instead of always returning to page 1 — the most common symptom being a paginated list quietly swapping to unrelated data on refresh.- In-flight request deduplication is now keyed by params, not just the chunk key. Two calls to
fetchDatawith different params (e.g. an unfiltered mount-timereload()immediately followed by a filteredsetParams()) previously deduped onto the same in-flight promise, since only the chunk's key was used for lookup. The second, correct request silently never reached the network — only the first (wrong) response was ever applied. This is the root cause behind filters not applying on first page load in some apps. cancel()updated to match the new params-aware dedup key — it previously deleted the in-flight entry under the old bare chunk-key, which no longer matched anything after the dedup fix above, leaving stale in-flight promises un-cancellable.- Cache eviction (
cacheTime) is now gated by active subscriber count. Previously,cacheTimescheduled an unconditionalclearCache()regardless of whether the chunk still had active subscribers — so live, in-use data could silently be wiped tonullmid-session once the timer elapsed, even while a component was still mounted and displaying it. Eviction now only fires oncesubscriberCountreaches zero, matching the documented intent of "cache retained after last subscriber leaves." fetchOnMountno longer bypassesenabledinuseAsyncChunk. The mount effect's condition previously short-circuited onfetchOnMountalone (fom || (...)), ignoringenabledentirely — chunks configured with bothfetchOnMount: trueandenabled: someCondition(e.g.isLoggedIn) fetched on mount even when the condition was false, producing unauthenticated requests immediately after logout + refresh. Now correctly requiresenabled && (fom || ...).reset()now refetches paginated chunks. Previouslyreset()only auto-refetched when the fetcher took no params (!expectsParams), which unconditionally skipped every paginated chunk (their fetcher signature always expectspage/pageSize/cursor). Paginated chunks manage pagination internally and don't need external params to refetch, so they're now included.useAsyncChunkresolves scoped/passed-in chunk instances viauseMemokeyed on the chunk reference, not a one-timeuseStateinitializer — restoring correct behavior when a component rerenders with a genuinely different chunk instance (e.g. switching from a paginated to a non-paginated chunk, or vice versa).
Removed
initialParamsfully removed fromUseAsyncChunkOptionsandUseInfiniteAsyncChunkOptions. It has been deprecated since 3.0.0-rc.10 in favor ofparams; both the type and the runtime fallback are now gone. Update any remaininguseAsyncChunk(chunk, { initialParams })call sites touseAsyncChunk(chunk, { params }).