Remix & React Router
Remix is a full-stack React framework built around web fundamentals: HTTP requests and responses, HTML forms, and nested routes that load their own data. In late 2024, Remix's features were merged into React Router v7, whose "framework mode" is now the continuation of Remix; the Remix team is developing a separate, next-generation "Remix 3." For most developers, "Remix" today means React Router v7 framework mode, and the concepts below apply to both.
The central idea is that each route module owns its loader (read data on the server), action (handle mutations on the server), UI, and error boundary. Mutations use real <form> submissions that work without JavaScript, and after every action the framework automatically revalidates the data on the page. That removes much of the client-side state management many React apps carry.
TL;DR
- Each route module exports a
loader, anaction, a component, and anErrorBoundary. - Loaders run on the server for GET requests; actions handle POST/PUT/DELETE.
<Form>submissions work without JavaScript and revalidate loaders automatically.- Nested routes load data in parallel and render inside parent layouts with
<Outlet />. useFetcherhandles mutations and loads that don't navigate.- Deploys to Node, serverless, and edge runtimes through adapters; built on Vite.
Quick Example
A route that lists and creates tasks (React Router v7 framework mode):
After the action succeeds, the loader reruns and the new task appears — no manual cache updates.
Core Concepts
Nested Routes
URL segments map to nested route modules; each renders inside its parent's <Outlet />. Because each segment declares its own loader, the framework fetches all of them in parallel instead of creating request waterfalls, and only reloads segments whose data changed on navigation.
Loaders and Actions
They use the standard Request and Response web APIs, so code is portable across runtimes.
Forms, Fetchers, and Revalidation
<Form> behaves like an HTML form but submits via fetch when JavaScript is available. useNavigation exposes pending states; useFetcher performs submissions or loads without navigating (for "like" buttons, inline edits, or comboboxes). After actions, loaders revalidate automatically, keeping UI and server data in sync. Optimistic UI is built from pending form data.
Streaming and Deferred Data
Return promises from loaders and render them with <Suspense> and <Await> to send critical data immediately and stream slower data later.
Rendering Modes
React Router v7 supports server rendering, static prerendering of chosen routes, and SPA mode, plus a "library mode" for adding routing to any React app without the framework features.
Best Practices
Put Data Needs in Loaders
Load everything a route renders in its loader; avoid useEffect fetching for route data.
Use Forms for Mutations
Native form semantics give progressive enhancement, accessibility, and automatic revalidation for free.
Authorize in Every Loader and Action
They're HTTP endpoints. Check the session and permissions each time, typically with a requireUser helper.
Add Error Boundaries at Meaningful Levels
Route-level boundaries keep a failure in one panel from blanking the entire page.
Keep Server-Only Code in .server Modules
Files ending in .server.ts are excluded from client bundles, protecting secrets and database clients.
Common Mistakes
Client-Side Fetching Out of Habit
Fetching in effects reintroduces loading spinners, waterfalls, and stale caches the loader model solves.
Returning Too Much From Loaders
Everything returned is serialized to the client. Select only the fields the UI needs, and never include secrets.
Forgetting Validation Feedback
Return validation errors from actions with a 400 status and render them; don't throw for expected user errors.
Treating It as a Static Site Generator
Remix/React Router shines with a server. If you deploy purely static, make sure prerendering or SPA mode is configured.
Comparison
FAQ
What happened to Remix?
Remix's framework features were merged into React Router v7. Existing Remix v2 apps upgrade to React Router v7 framework mode, and the Remix name is being used for a new, separate framework effort.
What's the difference between a loader and an action?
A loader reads data for GET requests before rendering a route. An action handles non-GET form submissions to change data, after which loaders revalidate.
Does Remix work without JavaScript?
Core navigation and form submissions do, because they're built on HTML links and forms. JavaScript enhances them with client-side transitions and pending states.
Remix or Next.js?
Choose Remix/React Router for a web-standards approach with loaders, actions, and HTTP caching. Choose Next.js for React Server Components, a broad feature set, and tight Vercel integration.
Related Topics
- React — The UI library underneath
- Next.js — The most popular React framework
- Data Fetching — Loading and caching server data
- Forms & Validation — Robust, accessible forms
- SEO for SPAs — Server rendering and metadata