Vai al contenuto
Pathrule

pattern

Questa pagina è disponibile solo in inglese.

React Router 7

Pathrule3 regole • 2 memorie • 1 skill

React Router 7 merges Remix into a single multi-strategy router with a full framework mode for SSR, data loading, and mutations. This pattern keeps your data flow on loaders and actions, your routes type-safe through codegen, and your navigation fast with single-fetch and prefetching. It is tuned for the 7.17+ API surface and the framework-mode conventions teams ship in 2026.

Mappa dei percorsi suggerita

Pathrule colloca ogni elemento sul percorso corrispondente, così il tuo assistente lo vede solo dove serve. È l'ambito che ottieni con l'importazione; puoi modificarlo nel tuo workspace.

/ radice del workspace
react-router-review
app/
Keep the route config and codegen in sync
Framework mode data flow and single-fetch
Middleware and request context (v8_middleware)
routes/
Load and mutate through loaders and actions
Use generated Route types, not hand-written ones

Regole

3
Load and mutate through loaders and actions/app/routesaltaconsultivaRoute data comes from loaders; mutations go through actions submitted with Form or useFetcher, never useEffect or ad-hoc fetch.
1In framework mode, route data and mutations live on the route module, not in component effects.
2 
3- Read data with `loader` (server) or `clientLoader` (browser); never fetch route data in `useEffect`.
4- Mutate with `action` / `clientAction` submitted via `<Form method="post">` or `useSubmit`, not `fetch` in click handlers. `<Form>` works before hydration, so submissions degrade gracefully without JS.
5- After an action resolves, every matched route loader revalidates automatically. Do not manually refetch. If you see stale data, check that a `shouldRevalidate` export is not returning `false` and blocking the re-run.
6- Use `useFetcher` for non-navigation mutations (likes, inline edits, autosave): it submits to an action and revalidates affected loaders without changing the URL.
7- For control flow, `throw redirect("/path")` from a loader/action instead of navigating imperatively in an effect.
8- Put server-only secrets and DB calls inside `loader`/`action`; that code is stripped from the client bundle. `clientLoader`/`clientAction` ship to the browser, so never put secrets there.
Use generated Route types, not hand-written ones/app/routesaltaconsultivaImport the per-route Route namespace for params, loaderData, and actionData typing; never edit generated files.
1React Router codegen emits a typed `Route` namespace per route file; use it instead of casting.
2 
3- Import with `import type { Route } from "./+types/<route-file>"` and type handlers as `Route.LoaderArgs`, `Route.ClientLoaderArgs`, `Route.ActionArgs`, `Route.ComponentProps`, `Route.ErrorBoundaryProps`, `Route.HydrateFallbackProps`.
4- The `+types/<name>` segment must mirror the route file name exactly, including `$` params and `.` separators (for example `./+types/posts.$id`). A mismatch is the most common "types are missing/wrong" cause.
5- Read `params`, `loaderData`, and `actionData` from the typed props rather than `useParams()` casts; `params` is typed from the route pattern and `loaderData` is inferred from the loader return.
6- Generated declarations live in `.react-router/types/`; they require `rootDirs` in `tsconfig.json` to resolve as if adjacent to the route. Keep `react-router dev` (or `react-router typegen --watch`) running so they stay current. Never hand-edit generated files and do not commit them.
Keep the route config and codegen in sync/appmediaconsultivaPick one routing strategy; an app/routes.ts disables file-based convention unless you explicitly spread it back in.
1Framework-mode routing is driven by `app/routes.ts`, and the codegen depends on it being correct.
2 
3- Define routes with the config helpers: `import { type RouteConfig, route, index, layout, prefix } from "@react-router/dev/routes"`.
4- Once `app/routes.ts` exists, the file-system convention is OFF by default. You must declare every route, or routes silently 404. To keep convention-based discovery, spread it back in explicitly: `import { flatRoutes } from "@react-router/fs-routes"` then `export default [route("/", "./home.tsx"), ...(await flatRoutes())] satisfies RouteConfig`.
5- Use `layout(file, children)` to nest UI without adding a URL segment, and `prefix(path, routes)` to add a path prefix without a new route module. Do not fake these with empty path segments.
6- Every route module referenced in `routes.ts` must exist and export a `default` component (or be a pure layout/resource route); a dangling reference breaks typegen for the whole app.

Memorie

2
Framework mode data flow and single-fetch/appHow loaders, actions, revalidation, single-fetch, and deferred streaming fit together in RR7 framework mode.
1Framework mode (the Remix-merged full-stack setup) drives the data lifecycle from route modules. We are on `react-router` 7.17.x; `react-router-dom` is folded into `react-router`, so import everything from `react-router`.
2 
3- One navigation triggers a single HTTP request (single-fetch) that resolves every matched route's loader together. Avoid waterfalling per-component fetches; co-locate data needs on the route loaders.
4- On initial load/SSR the server `loader` runs; on client navigations the server loader is called via an automatic browser fetch. `clientLoader` runs only on the client unless you opt it into hydration.
5- To run a `clientLoader` during hydration, export `clientLoader.hydrate = true as const` and provide a `HydrateFallback` component to render while it runs.
6- Stream slow data: return a promise from a loader and render it with `<Await>` + `<Suspense>` (or `useAsyncValue`) so the shell paints immediately. Loader serialization also handles Dates, Maps, Sets, and promises, not just primitives.
7- Single-fetch merges loader responses; when multiple matched loaders set headers, the deepest matching route wins. Set response headers from the leaf loader/action that owns them.
8 
9See /app/routes for the load/mutate and generated-types rules, and the middleware memory at /app for the request-pipeline layer.
Middleware and request context (v8_middleware)/appRR7 middleware runs before loaders/actions for auth, logging, and shared context; it is behind a future flag with a strict next() contract.
1React Router 7.17 ships middleware behind a future flag; it is the canonical place for auth, logging, and seeding per-request context. It is slated to become default in v8, so the API is stable enough to adopt now.
2 
3- Enable it in `react-router.config.ts`: `export default { future: { v8_middleware: true } } satisfies Config`. In data mode (`createBrowserRouter`) you also augment the `Future` interface via `declare module "react-router"`.
4- A route exports `middleware: Route.MiddlewareFunction[]` (server) and/or `clientMiddleware: Route.ClientMiddlewareFunction[]`. Each entry receives `({ request, context }, next)` and runs before that route's loader/action.
5- Contract: call `await next()` to continue the chain; on the SERVER you must return the response (`return await next()`), and post-`next()` code runs after handlers (for timing, header rewriting). On the client `next()` is optional. `next()` may be called at most once and never throws; thrown errors route to the nearest `ErrorBoundary`.
6- Share data through typed context, not module globals: `const userCtx = createContext<User | null>(null)`, then `context.set(userCtx, user)` in middleware and `context.get(userCtx)` in downstream middleware/loaders. With a custom server, return a `new RouterContextProvider()` from `getLoadContext`.
7- Auth pattern: in middleware, load the session and `throw redirect("/login")` when missing, otherwise `context.set(userCtx, user)` so every loader on the route reads an authenticated user without re-checking.
8 
9See /app for the single-fetch data-flow memory and /app/routes for the loader/action rules that consume this context.

Skill

1
react-router-review/rootPre-merge checklist for React Router 7 framework mode routes, loaders, actions, and middleware.
1---
2name: react-router-review
3description: Review a React Router 7 framework-mode change before merging. Use when adding or changing route modules, loaders, actions, middleware, or app/routes.ts.
4---
5 
6# React Router 7 review
7 
8## Data and mutations
9- [ ] Route data is read via `loader` / `clientLoader`, not `useEffect` fetches
10- [ ] Mutations go through `action` / `clientAction` submitted with `<Form>` or `useFetcher`, not raw `fetch` in handlers
11- [ ] No manual refetch after an action; rely on automatic revalidation (check any `shouldRevalidate` does not block needed loaders)
12- [ ] `useFetcher` is used for non-navigation mutations (likes, inline edits) instead of changing the URL
13- [ ] Slow data is deferred with a returned promise + `<Await>` / `<Suspense>` instead of blocking the whole route
14- [ ] Redirects use `throw redirect()` from loaders/actions, not imperative navigation in effects
15 
16## Type safety
17- [ ] Args and props use generated `Route.LoaderArgs` / `Route.ActionArgs` / `Route.ComponentProps` from `./+types/...`
18- [ ] The `+types/<name>` import path mirrors the route file name exactly (including `$` params and `.` separators)
19- [ ] `params`, `loaderData`, `actionData` come from typed props, not `useParams()` casts
20- [ ] No generated files (`.react-router/types/`) were hand-edited or committed
21 
22## Routing config
23- [ ] New route is registered in `app/routes.ts` via `route` / `index` / `layout` / `prefix` (or covered by a spread `flatRoutes()`)
24- [ ] Every referenced route module exists and exports a `default` (or is a deliberate layout/resource route)
25 
26## Middleware and security
27- [ ] Server-only code (secrets, DB) stays inside `loader` / `action` / `middleware`, never in `clientLoader` / `clientAction`
28- [ ] Middleware calls `await next()` and returns its response on the server; shared state goes through `createContext` + `context.set/get`, not module globals
29- [ ] Auth/redirect checks live in `middleware` (or a loader) rather than being duplicated per component
30 
31## Resilience
32- [ ] `<Link>` uses an appropriate `prefetch` mode (`intent` / `viewport` / `render`) for hot navigations
33- [ ] Route exports an `ErrorBoundary` (and `meta` where needed) for failure and SEO paths

Perché questo pattern

Agents write React Router 7 like v6 SPAs, fetching in effects and ignoring loaders, actions, and generated route types.

Pensato per: Teams building full-stack React apps on React Router 7 framework mode.

Aiuta il tuo assistente a evitare:

  • Fetching data in useEffect instead of route loaders
  • Hand-typing route params and loaderData instead of using generated Route types
  • Mutating data with fetch in event handlers instead of route actions
Licenza
Apache-2.0
Versione
1.0.1
Aggiornato
2026-08-25
Vedi il sorgente