react-router

React Router v7 Data Mode for Vite SPA with Convex backend. Triggers on routing, navigation, nested routes, protected routes, lazy loading. Use for client-side routing in Vite React apps.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "react-router" with this command: npx skills add sebastiaanwouters/dotagents/sebastiaanwouters-dotagents-react-router

React Router v7 (Data Mode for Vite SPA + Convex)

Use Data Mode (createBrowserRouter + RouterProvider) for Vite SPAs with Convex.

Attribution: remix-run/react-router

Key Principle

Convex handles data, Router handles navigation.

  • React Router: routing, navigation, URL params, nested layouts, lazy loading
  • Convex: data fetching (useQuery), mutations (useMutation), real-time updates

Don't use React Router loaders/actions with Convex.

Installation

react-router-dom

(Install with your project's package manager)

Basic Setup

// main.tsx
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { ConvexProvider, ConvexReactClient } from "convex/react";

const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL);

const router = createBrowserRouter([
  {
    path: "/",
    Component: Layout,
    ErrorBoundary: RootError,
    children: [
      { index: true, Component: Home },
      { path: "projects", Component: Projects },
      { path: "projects/:projectId", Component: Project },
    ],
  },
]);

// HMR cleanup for Vite
if (import.meta.hot) {
  import.meta.hot.dispose(() => router.dispose());
}

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <ConvexProvider client={convex}>
      <RouterProvider router={router} fallbackElement={<p>Loading...</p>} />
    </ConvexProvider>
  </StrictMode>
);

Nested Routes & Outlet

function Layout() {
  return (
    <div>
      <nav>
        <Link to="/">Home</Link>
        <Link to="/projects">Projects</Link>
      </nav>
      <Outlet /> {/* Child routes render here */}
    </div>
  );
}

URL Params + Convex Query

function Project() {
  const { projectId } = useParams<{ projectId: string }>();
  
  const project = useQuery(
    api.projects.get,
    projectId ? { id: projectId as Id<"projects"> } : "skip"
  );

  if (project === undefined) return <p>Loading...</p>;
  if (project === null) return <p>Not found</p>;

  return <h1>{project.name}</h1>;
}

Mutation + Navigate

function CreateProject() {
  const navigate = useNavigate();
  const createProject = useMutation(api.projects.create);

  async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    const formData = new FormData(e.currentTarget);
    const id = await createProject({ name: formData.get("name") as string });
    navigate(`/projects/${id}`);
  }

  return (
    <form onSubmit={handleSubmit}>
      <input name="name" required />
      <button type="submit">Create</button>
    </form>
  );
}

Protected Routes

function ProtectedRoute() {
  const { isAuthenticated, isLoading } = useConvexAuth();
  const location = useLocation();

  if (isLoading) return <p>Loading...</p>;
  if (!isAuthenticated) {
    return <Navigate to="/login" state={{ from: location }} replace />;
  }
  return <Outlet />;
}

// Usage in router
{
  Component: ProtectedRoute,
  children: [
    { path: "dashboard", Component: Dashboard },
  ],
}

Quick Reference

TaskAPI
Navigate programmaticallyuseNavigate()
Get URL paramsuseParams()
Get/set search paramsuseSearchParams()
Get current locationuseLocation()
Check navigation stateuseNavigation()
Link with active state<NavLink>
Render child routes<Outlet />
Code split routeslazy: () => import()

Critical Rules

  1. Use Convex hooks for data - useQuery/useMutation provide real-time updates
  2. Don't use loaders/actions - Convex handles data, Router handles navigation
  3. Handle loading states - useQuery returns undefined while loading
  4. Dispose router in HMR - Prevents memory leaks in Vite dev mode
  5. Wrap Router in ConvexProvider - Convex context must be available

Deep Dive References

  • examples.md - Complete CRUD, auth patterns, search params
  • api.md - All hooks and components reference

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

simplify-code

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

svelte-code-writer

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

skill-from-github

No summary provided by upstream source.

Repository SourceNeeds Review