Last 12 weeks · 23 commits
4 of 6 standards met
Fixes #2888 Summary allow an explicit null fetcher to override an inherited global fetcher preserve global fetcher behavior when the hook fetcher is omitted add runtime and type coverage for the null and omitted cases Validation git apply --check --recount: passed git diff --check: passed local Jest/type checks unavailable because this checkout has no node_modules; CI should run the full workflow.
Closes #4261 Summary Remove the final subscriber's stale ref-count and disposer entries from the cache-bound Maps. Add a regression test covering deduplication, disposal, and a fresh remount. Verification local verification not run; relying on upstream CI The worktree has no installed , so the repository's Jest command cannot run locally.
Problem When is set and is present for the key, current implementation does not revalidate on unmount/remount even when is set, preventing automatic client-side mount revalidation indefinitely when both options are used. This PR restores the normal / behavior after the server-loaded value has entered the SWR cache. Context: In our app, we rely on automatic remount revalidation on SPA navigation to achieve MPA-like refetch behavior so that we only have to cal keys within the same page for UI consistency. We still want to skip initial duplicate fetches but need remount re-validations to achieve this behavior. Summary Skip revalidation only for the render where no cached data exists Extend the RSC preload E2E to cover unmounting and remounting behaviors with suspense: true Behavior This PR now covers common application behaviors for suspense-enabled SWR hooks Allows re-mount revalidations but skips initial duplicate client-side mount revalidation with (default) Skip mount revalidation indefinitely with Allows initial duplicate client-side revalidation and later remount revalidations with explicit (unchanged) Tests Added unit tests and e2e tests to cover those scenarios
Closes #4261. Summary (ref-count) and (cleanup function) Maps in live for the lifetime of the cache via . The previous teardown called on the last subscriber but never removed the now-stale entries — long-lived apps with rotating subscription keys (paginated feeds, live channels, rotating market tickers, etc.) accumulated one dead entry in each Map per unique key, plus one un-collectable dispose closure per key, growing proportional to total keys ever seen rather than currently-active ones. Fix Delete both entries immediately after invoking : Behaviour is unchanged for live subscriptions and same-key remounts — the existing fallback in the mount path was already tolerant of zero-count stale entries, so the functional contract is preserved. Tests All 7 existing tests pass unchanged. I did not add a behavioural regression test: the only observable effect of the bug is / growth on the module-scoped WeakMap, which has no public introspection surface. Adding one would require exporting (with ) just for the test, which felt like a heavier change than the two-line fix warrants. Happy to add an export and a size-tracking test if you'd prefer that shape — the repro scenario from #4261 lifts directly into a test once an introspection hook exists. The fix is auditable by inspection against the issue's reproduction:
Summary Hydrate request-scoped into SWR's cache for without treating hydration as revalidation. Support plain, promised, and rejected values. Keep each key one-shot per request-scoped object. Share consumption state across fetcher, fetcherless, and Suspense paths. Avoid client fetching, validation state, retries, and revalidation callbacks during hydration. Problem Default-mode was consumed inside . A hook without a fetcher never enters that path, so remained undefined and the server-loaded value was never written into SWR's cache. Tracking consumption only by serialized key also cannot distinguish a fresh request-scoped object from an already-consumed one. Promised values additionally need protection from key changes and newer local mutations. Solution After React commits, a fetcherless hook resolves its matching value and writes the resulting data or error into the external cache. The commit proceeds only while: the hook still owns the same key; no newer mutation has started; and the cache entry remains empty. A per-hook tracks consumption by request object and serialized key. This lets a fresh request provide new data for the same key while old request objects remain eligible for garbage collection. Hydration does not call , so and remain false, revalidation callbacks do not fire, and no client fetcher runs. Validation Jest: 34 suites passed; 374 tests passed and 5 skipped. Playwright: 7 promise-scenario tests plus dev-server warmup passed. passed. passed. passed. The browser regression verifies real RSC hydration with : the server value reaches both the hook and SWR cache, loading and validating stay false, success callbacks remain at zero, and no client request occurs.
Repository: vercel/swr. Description: React Hooks for Data Fetching Stars: 32455, Forks: 1377. Primary language: TypeScript. Languages: TypeScript (99.5%), JavaScript (0.5%). License: MIT. Homepage: https://swr.vercel.app Topics: cache, data, data-fetching, fetch, hook, hooks, nextjs, react, react-native, stale-while-revalidate, suspense, swr, vercel. Latest release: v2.5.0 (1w ago). Open PRs: 69, open issues: 145. Last activity: 13h ago. Community health: 100%. Top contributors: shuding, huozhi, promer94, koba04, vercel-release-bot, dependabot[bot], sergiodxa, cryptiklemur, matamatanot, anothertempore and others.