mcpField
R
react-router-v7

react-router-v7

github.com/existential-birdsDevelopment85573 installsUpdated 11w ago
Repository

About react-router-v7

A reference skill for developers building applications with React Router v7. It organizes routing, data loading, mutations, and mode selection around practical decision points.

Key features

  1. 01Nested routes and dynamic segments
  2. 02Framework, Data, and Declarative modes
  3. 03Loader versus useEffect guidance
  4. 04Form versus useFetcher guidance
  5. 05References for loading and navigation

Use cases

  1. 01Choose a routing mode for an application
  2. 02Load data required for the initial render
  3. 03Handle inline mutations without navigation
  4. 04Configure nested and parameterized routes

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/existential-birds/beagle --skill react-router-v7

After installing, type/react-router-v7in Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

ACTIONS.md
ADVANCED.md
LOADERS.md
NAVIGATION.md
references/
actions.md
advanced.md
loaders.md
navigation.md

Details

From the project README

React Router v7 Best Practices

Quick Reference

Router Setup (Data Mode):

import { createBrowserRouter, RouterProvider } from "react-router";

const router = createBrowserRouter([
  {
    path: "/",
    Component: Root,
    ErrorBoundary: RootErrorBoundary,
    loader: rootLoader,
    children: [
      { index: true, Component: Home },
      { path: "products/:productId", Component: Product, loader: productLoader },
    ],
  },
]);

ReactDOM.createRoot(root).render(<RouterProvider router={router} />);

Framework Mode (Vite plugin):

// routes.ts
import { index, route } from "@react-router/dev/routes";

export default [
  index("./home.tsx"),
  route("products/:pid", "./product.tsx"),
];

Route Configuration

Nested Routes with Outlets
createBrowserRouter([
  {
    path: "/dashboard",
    Component: Dashboard,
    children: [
      { index: true, Component: DashboardHome },
      { path: "settings", Component: Settings },
    ],
  },
]);

function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>
      <Outlet /> {/* Renders child routes */}
    </div>
  );
}
Dynamic Segments and Splats
{ path: "teams/:teamId" }           // params.teamId
{ path: ":lang?/categories" }       // Optional segment
{ path: "files/*" }                 // Splat: params["*"]

Key Decision Points

Form vs Fetcher

Use <Form>: Creating/deleting with URL change, adding to history Use useFetcher: Inline updates, list operations, popovers - no URL change

Loader vs useEffect

Use loader: Data before render, server-side fetch, automatic revalidation Use useEffect: Client-only data, user-interaction dependent, subscriptions

Gates (decision sequencing)

Answer in order. Pass means the condition is true; pick the API on the same line and stop.

<Form> vs useFetcher
  1. Must the URL or history stack change (bookmark/share, back returns to prior screen)?
    • Pass → <Form> / route action (or useSubmit + navigation). Stop.
    • Fail → Step 2.
  2. Mutation stays on the same route (inline edit, modal, list row, no address change)?
    • Pass → useFetcher(). Stop.
    • Fail → Re-check step 1; you may need a dedicated action route or POST to the current URL.
loader vs useEffect
  1. Is data needed for correct first render (or your intended <Suspense> boundary) for this route?
    • Pass → loader (Framework: clientLoader when appropriate). Stop.
    • Fail → Step 2.
  2. Fetch only after mount from user action, timer, or subscription (not route entry)?
    • Pass → useEffect / event handlers. Stop.
    • Fail → Prefer loader + revalidation over an effect that mirrors navigation.

Additional Documentation

Mode Comparison

FeatureFramework ModeData ModeDeclarative Mode
SetupVite plugincreateBrowserRouter<BrowserRouter>
Type SafetyAuto-generated typesManualManual
SSR SupportBuilt-inManualLimited
Use CaseFull-stack appsSPAs with controlSimple/legacy

Comments

Markdown supported