Building a Multi-Page SPA with React RouterEntry 1 of 20
Router Setup: createBrowserRouter and RouterProvider
createBrowserRouter builds the router from an array of route objects, and <RouterProvider> renders it. Together they enable client-side routing: the URL changes and the matching component renders without a full page reload.
Notes
- A route object maps a
pathto anelement, like Angular'spath→component. <RouterProvider router={router} />replaces the app's root content, similar toprovideRouter(routes)+<router-outlet>.- Route object properties:
| Property | Description | Example |
|---|---|---|
path | URL pattern. Supports dynamic segments (:id) and catch-all (*). | 'events/:eventId' |
element | Component to render when the route matches. | <EventsPage /> |
errorElement | Rendered if a loader, action, or render throws in this route or its children. | <ErrorPage /> |
children | Nested routes, rendered in the parent's <Outlet />. | [{ path: 'new', element: <NewEventPage /> }] |
index | Default child when the parent's path matches exactly. | { index: true, element: <HomePage /> } |
loader | Fetches data before rendering. Receives { params, request }. | loader: eventsLoader |
action | Handles mutations (form submissions). Receives { params, request }. | action: newEventAction |
id | Names the route so children can read its loader data. | id: 'event-detail' |
What / Why / When
- What
The router instance and its entry point.
- Why
A multi-page experience in a single-page app: bookmarkable URLs, back/forward support, no reloads.
- When
Any React app with more than one screen.
Code compare
// App.tsximport { createBrowserRouter } from "react-router";import { RouterProvider } from "react-router/dom";import HomePage from "./pages/Home";import ProductsPage from "./pages/Products";const router = createBrowserRouter([ { path: "/", element: <HomePage /> }, { path: "/products", element: <ProductsPage /> },]);export default function App() { return <RouterProvider router={router} />;}// app.routes.tsimport { Routes } from "@angular/router";export const routes: Routes = [ { path: "", loadComponent: () => import("./pages/home.component").then((m) => m.HomeComponent) }, { path: "products", loadComponent: () => import("./pages/products.component").then((m) => m.ProductsComponent), },];// app.config.tsimport { provideRouter, withComponentInputBinding } from "@angular/router";import { routes } from "./app.routes";export const appConfig: ApplicationConfig = { providers: [provideRouter(routes, withComponentInputBinding())],};// app.component.ts@Component({ selector: "app-root", imports: [RouterOutlet], template: `<router-outlet />`,})export class AppComponent {}Differences and gotchas
- React paths can start with
/; Angular paths never do ('products', not'/products'). - Angular lazy-loads with
loadComponent. React Router's equivalent is the route'slazyproperty. - Create the router outside the component so it isn't recreated on every render.
Quick reference
| React | Angular |
|---|---|
createBrowserRouter(routes) | provideRouter(routes) |
<RouterProvider router={router} /> | <router-outlet /> in root |
element | component / loadComponent |
lazy | loadComponent / loadChildren |