Decision: Already on React Router v6+? Stay — v6→v7→v8 is near-drop-in in library mode (imports + future flags), and a codemod automates ~85-90% of it [1]. Greenfield admin SPA and TypeScript-first? TanStack Router ⭐ 15k is the better bet — no framework server, 100% type-safe routes, and lighter churn history [5]. Switching routers later costs 2-4 hours for a small SPA, weeks for a data-heavy one [4].
Staying on React Router: cheap, if you’ve been keeping up
React Router ⭐ 56k (Jul 2026) now ships v8, its “most boring” major yet — breaking changes are pre-adoptable in v7 behind future.* flags, so upgrading is: flip flags, remove deprecated APIs, bump the dep [3]. In library mode (client-only SPA), v6→v7 is effectively just import rewrites; the react-router-v6-to-v7-pro codemod automated ~85-90% across 461 real files with zero false positives [1]. The cost only balloons if you also adopt the Remix-inherited data-router (loaders/actions): a 20-30 route app then runs ~3 weeks [6].
The churn tax is real
The pain is history, not the current step. The v5→v6 rewrite (Switch→Routes, component→element, hooks) was disruptive, and Shopify’s 2022 Remix acquisition merged Remix into v7 — a library→framework paradigm shift, with @remix-run/* packages renamed @react-router/* and legacy APIs dropped [7]. Community gripe: “forwards compat is a feature” they keep breaking [6]. The future-flags cadence has since tamed this [3].
Lock-in & escape hatches
| Axis | React Router v8 | TanStack Router |
|---|---|---|
| Framework server needed | ✗ (library mode is first-class) | ✗ (router is standalone; Start is opt-in) |
| File-based conventions | Optional | Optional (code-based also supported) |
| Loader coupling | Remix-style loaders/actions | Loaders, but decoupled + typed |
| Type safety | Good | Excellent (typed params/search) [5] |
| Ecosystem size | Largest [2] | Growing |
Neither forces a server for a client-rendered SPA. Real lock-in comes from loaders/actions and file-route conventions — avoid those and either router stays a thin, swappable dependency. The two can coexist during a migration [8]. Switching effort: 2-4 hours for a small SPA using standard patterns [4], 3-6 weeks for a medium app leaning on framework-specific features [8].
Bottom line for an itenium-ui-style console: an existing RR app should ride the flags forward; a greenfield one gains type safety and lighter lock-in from TanStack Router. Keep data-fetching out of route loaders and either stays cheap to leave.