DEV Community

Alex Spinov
Alex Spinov

Posted on

React Router v7 Has a Free Full-Stack Framework Hidden Inside

React Router v7 is not just a routing library anymore. It is a full-stack React framework — the spiritual successor to Remix, merged directly into React Router.

The Big Change

Remix and React Router merged. React Router v7 now includes:

  • File-based routing
  • Server-side rendering
  • Data loading (loaders)
  • Data mutations (actions)
  • Streaming
  • Progressive enhancement

Framework Mode

npx create-react-router@latest my-app
cd my-app && npm run dev
Enter fullscreen mode Exit fullscreen mode

File-Based Routes

app/
  routes/
    _index.tsx        → /
    about.tsx         → /about
    users.tsx         → /users (layout)
    users.$id.tsx     → /users/:id
    blog._index.tsx   → /blog
    blog.$slug.tsx    → /blog/:slug
Enter fullscreen mode Exit fullscreen mode

Loaders (Server-Side Data)

// app/routes/users.$id.tsx
import type { Route } from "./+types/users.$id";

export async function loader({ params }: Route.LoaderArgs) {
  const user = await db.user.findUnique({ where: { id: params.id } });
  if (!user) throw new Response("Not Found", { status: 404 });
  return { user };
}

export default function UserProfile({ loaderData }: Route.ComponentProps) {
  const { user } = loaderData;
  return <h1>{user.name}</h1>;
}
Enter fullscreen mode Exit fullscreen mode

Actions (Mutations)

export async function action({ request }: Route.ActionArgs) {
  const formData = await request.formData();
  const name = formData.get("name") as string;
  await db.user.update({ where: { id: params.id }, data: { name } });
  return { success: true };
}

export default function EditUser({ loaderData }: Route.ComponentProps) {
  return (
    <Form method="post">
      <input name="name" defaultValue={loaderData.user.name} />
      <button type="submit">Save</button>
    </Form>
  );
}
Enter fullscreen mode Exit fullscreen mode

Forms work without JavaScript — progressive enhancement by default.

Type Safety

React Router v7 generates types for every route automatically:

// Route.LoaderArgs includes typed params
// Route.ComponentProps includes typed loaderData
// No more `useLoaderData<typeof loader>()`
Enter fullscreen mode Exit fullscreen mode

Library Mode (Just Routing)

Don't need full-stack? Use React Router v7 as a plain router:

import { BrowserRouter, Routes, Route } from "react-router";

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </BrowserRouter>
  );
}
Enter fullscreen mode Exit fullscreen mode

Migration from v6

npx codemod react-router/6/to/7
Enter fullscreen mode Exit fullscreen mode

Key changes:

  • react-router-domreact-router
  • json() utility removed (just return objects)
  • New type-safe route modules

Why Choose React Router v7

  • Most downloaded React library (20M+ weekly npm downloads)
  • Full-stack OR client-only — your choice
  • Progressive enhancement built-in
  • Streaming SSR support
  • Nested layouts and error boundaries
  • Works with Cloudflare Workers, Deno, Node.js

Building web applications that need robust data handling? I create data extraction and API integration solutions. Contact spinov001@gmail.com or check my Apify tools.

Top comments (0)