TanStack Router has replaced its single monolithic router.state object with a graph of smaller, independent stores that serve as the internal source of truth, with router.state now derived from them for backward compatibility. This narrows change propagation so navigation triggers fewer subscriber updates, verified via CodSpeed benchmarks on a synthetic rerender-heavy page. The store layer is now defined behind a shared contract, letting each framework adapter plug in its own implementation: React and Vue use TanStack Store, while Solid uses native Solid signals (backed by memos and a FinalizationRegistry for cleanup). The tradeoff is bundle size: React and Vue bundles grew slightly since representing several stores costs more code than one state object, while Solid's bundle shrank because it no longer depends on tanstack/store. No public API changes are required; useMatch, useLocation, and Link keep the same surface.
Table of contents
Old Model: One Broad Router State #Problem: Routing State Changes in Smaller Pieces #New Model: Smaller Stores Become the Source of Truth #Hook-Level Change: Subscribe to the Relevant Store #Store Boundary: One Contract, Multiple Implementations #Observable Result: Less Work During Navigation #Closing #Footnotes #Questions this post answers
What changed internally in TanStack Router's reactive state model?
TanStack Router replaced its single router.state object as the internal source of truth with a graph of smaller, independently updating stores; router.state is now a derived snapshot kept for backward compatibility. This narrows change propagation during navigation, since consumers like useMatch can subscribe directly to the specific store they need instead of selecting from one large state object. No public API changes are required. Track internal refactors like this signal graph change before upgrading a TanStack Router app on daily.dev.
Does TanStack Router's new store-based architecture affect bundle size?
Yes, bundle size shifts differ by framework adapter. React and Vue bundles increased slightly since modeling several stores takes more code than one state object (both use TanStack Store internally), while Solid's bundle decreased because its adapter now uses native Solid signals and memos instead of depending on tanstack/store. Compare framework-specific tradeoffs like these on daily.dev before picking a router adapter.
How does useMatch subscribe to router state after TanStack Router's signal graph refactor?
useMatch now resolves the relevant match store directly via router.stores.getMatchStoreByRouteId(routeId) and subscribes to it with useStore, instead of subscribing through the whole router state object and filtering state.matches for the right match. getMatchStoreByRouteId creates the derived store on demand and caches it in an LRU cache so other subscribers can reuse it without leaking memory. Follow internal implementation details like this on daily.dev when debugging router performance.