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 path to an element, like Angular's path → component.
  • <RouterProvider router={router} /> replaces the app's root content, similar to provideRouter(routes) + <router-outlet>.
  • Route object properties:
PropertyDescriptionExample
pathURL pattern. Supports dynamic segments (:id) and catch-all (*).'events/:eventId'
elementComponent to render when the route matches.<EventsPage />
errorElementRendered if a loader, action, or render throws in this route or its children.<ErrorPage />
childrenNested routes, rendered in the parent's <Outlet />.[{ path: 'new', element: <NewEventPage /> }]
indexDefault child when the parent's path matches exactly.{ index: true, element: <HomePage /> }
loaderFetches data before rendering. Receives { params, request }.loader: eventsLoader
actionHandles mutations (form submissions). Receives { params, request }.action: newEventAction
idNames 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

React
// 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} />;}
Angular
// 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),  },];
Angular
// app.config.tsimport { provideRouter, withComponentInputBinding } from "@angular/router";import { routes } from "./app.routes";​export const appConfig: ApplicationConfig = {  providers: [provideRouter(routes, withComponentInputBinding())],};
Angular
// 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's lazy property.
  • Create the router outside the component so it isn't recreated on every render.

Quick reference

ReactAngular
createBrowserRouter(routes)provideRouter(routes)
<RouterProvider router={router} /><router-outlet /> in root
elementcomponent / loadComponent
lazyloadComponent / loadChildren