--- name: react-router description: Use react-router ^8.0.0 APIs correctly, including v8 import boundaries, pure path helpers, and the parts that require a React or framework runtime. --- Verified against react-router@8.3.1 on 2026-09-08. 2 of 2 examples executed. # react-router ^8.0.0 ## Version and module boundary - The v8 line is ESM-only and requires Node 22.22.0+, React 19.2.7+, and Vite 7+. - Import general routing APIs from `react-router`: ```ts import { Link, Route, createBrowserRouter } from "react-router"; ``` - Import DOM-specific `RouterProvider` and `HydratedRouter` from `react-router/dom`: ```ts import { RouterProvider, HydratedRouter } from "react-router/dom"; ``` - Do not use the older v7 compatibility shape with `react-router-dom`; v8 removes `react-router-dom`. - `createBrowserRouter(routes, opts?)` creates a data router backed by `history.pushState` and `history.replaceState`. Its result is passed to `RouterProvider`. ## Pure path helpers ### `generatePath` `generatePath(originalPath, params?)` substitutes route parameters and URL-encodes parameter values. ```ts import { generatePath } from "react-router"; const userPath = generatePath("/users/:id", { id: "123" }); const filePath = generatePath("/files/:name", { name: "a b" }); ``` `userPath` is `/users/123`; `filePath` is `/files/a%20b`. ```ts pmcp-example import assert from "node:assert/strict"; import { generatePath } from "react-router"; assert.equal(generatePath("/users/:id", { id: "123" }), "/users/123"); assert.equal(generatePath("/files/:name", { name: "a b" }), "/files/a%20b"); ``` ### `matchPath` `matchPath(pattern, pathname)` returns a path match or `null`. When the pattern is a string, its defaults are `caseSensitive: false` and `end: true`. The result contains the parsed route parameters. ```ts pmcp-example import assert from "node:assert/strict"; import { matchPath } from "react-router"; const match = matchPath("/users/:id", "/USERS/123"); assert.ok(match); assert.equal(match.params.id, "123"); assert.equal(matchPath("/users/:id", "/users/123/settings"), null); ``` ## React-bound APIs ### `useRoutes` `useRoutes(routes, locationArg?)` is a React hook that renders the element matched by a route-object tree. It must be called from a React component, not from a plain script or at module scope. The route tree can contain nested children: ```tsx function App() { return useRoutes([ { path: "/", element: , children: [ { path: "messages", element: }, { path: "tasks", element: }, ], }, { path: "team", element: }, ]); } ``` No standalone `ts pmcp-example` is provided for this hook because executing it requires a React render environment, which a direct `bun example.ts` process does not provide. ### `createBrowserRouter` `createBrowserRouter` is a DOM data-router API. Create the router from route objects and pass it to `RouterProvider` imported from `react-router/dom` in a browser application. A direct script has no browser history or DOM setup, so this API is exercised through the application/tool runtime rather than a standalone example. ## v8 migration traps - Do not import `RouterProvider` or `HydratedRouter` from `react-router`; use `react-router/dom`. - Do not import from `react-router-dom`; it was retained as a v7 re-export but is removed in v8. - The deprecated `meta` data is removed. Use `loaderData` in `MetaArgs`, `MetaMatch`, `Route.ComponentProps.matches`, and `UIMatch`. - Middleware is always enabled. Loader, action, and middleware `context` is always a `RouterContextProvider`; a custom `getLoadContext` must return that type rather than a plain object. - `future.v8_*` flags are removed or promoted to defaults. In particular, `future.v8_splitRouteModules` is replaced by top-level `splitRouteModules`, whose documented values include `false` and `"enforce"`; its default is `true`. - `hasErrorBoundary` is no longer accepted on route objects, JSX route props, or lazy route definitions. ## Framework and server boundaries Framework Mode depends on `@react-router/dev`'s Vite plugin for type-safe route modules, code splitting, SPA/SSR/SSG, and generated route types. Its setup is CLI/build-oriented rather than a self-contained package API. `ServerRouter` is a framework-entry API. It requires the generated/server entry context and is not a standalone helper for a plain script. ## Not covered This skill does not cover the complete route-object type surface, loaders and actions, middleware implementation, `RouterProvider` options, framework route-file conventions, generated route types, SSR/SSG setup, or the `ServerRouter` entry context. The available research also does not establish a standalone Node-only data-router setup.