Router Modes

Declarative, Data and Framework Modes

React Router 8 139,386 is three products in one package, layered so each mode is the previous one plus more. Which mode you are in is decided by a single line: how the router gets into your tree.

The three modes of React Router 8
Mode How the router is created Adds
Declarative <BrowserRouter> wrapping <Routes> URL matching, links, hooks
Data createBrowserRouter([...]) + <RouterProvider> loaders, actions, fetchers, pending UI
Framework routes.ts + the @react-router/dev Vite 25,978 plugin typed routes, code splitting, SSR/SSG

Everything in this section is declarative mode, because that is where the vocabulary lives: <Route>, path patterns, <Link>, useParams, useNavigate and useLocation behave identically in all three modes, so a component written against them is portable. What declarative mode cannot do is load data — the loader/action family, useFetcher, useNavigation and useBlocker all throw outside a data router, so you fetch in effects as in Fetching Data in an Effect. Framework mode goes further and owns the build too, making it a competitor to Next.js 10,514 (Next.js).

Pick declarative mode when something else — TanStack Query 79,069 , Redux 3,824 — already does the fetching, and data mode the moment you catch yourself writing the same "loading, error, data" effect in every screen. Data Routers shows that upgrade: the same route tree, written as objects instead of JSX.