Full-project lesson · needs Node.js, npm and real project files, so it does not run in the in-page playground.
This lesson shows how routes are described, in the two styles you will meet: JSX routes (declarative mode) and a route object array (data mode). Both use the same concepts.
JSX routes
You have seen this style:
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
The ideas to know:
pathis matched against the URL. Matching ignores trailing slashes and is case-insensitive by default.elementis the JSX to render when it matches.- Routes are matched by specificity, not only by order, so you do not need to worry much about the order of routes.
- A route with
path="*"matches anything not matched by other routes; see Not Found Pages.
Path patterns
| Pattern | Matches | Notes |
|---|---|---|
/about | /about | A static path |
/products/:id | /products/42 | :id is a dynamic segment; see Route Parameters |
/files/* | /files/a/b/c | A splat: matches the rest of the path |
/users/:id? | /users and /users/7 | Optional segment |
* | everything else | Used for “not found” |
Query strings (?page=2) are not part of a path; read them with useSearchParams.
Index routes
An index route is the default child of a parent path: the one that shows when the URL is exactly the parent’s. It has no path of its own, just index:
<Route path="/dashboard" element={<DashboardLayout />}>
<Route index element={<DashboardHome />} /> {/* /dashboard */}
<Route path="settings" element={<Settings />} /> {/* /dashboard/settings */}
</Route>
Nesting is covered in Nested Routes.
Route objects (data mode)
The second style describes routes as plain objects in an array, and gives them to createBrowserRouter. It looks like this in src/main.jsx:
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { createBrowserRouter, RouterProvider, Link } from 'react-router'
import './index.css'
function Home() {
return (
<div>
<h1>Welcome to the shop</h1>
<nav>
<Link to="/">Home</Link> | <Link to="/products">Products</Link>
</nav>
</div>
)
}
function Products() {
return (
<div>
<h1>Product list</h1>
<Link to="/">Back home</Link>
</div>
)
}
const router = createBrowserRouter([
{ path: '/', Component: Home },
{ path: '/products', Component: Products },
])
createRoot(document.getElementById('root')).render(
<StrictMode>
<RouterProvider router={router} />
</StrictMode>,
)
(Built with Vite and tested in a browser, including opening /products directly.)
Differences from JSX routes:
createBrowserRouter([...])creates the router outside React, once.<RouterProvider router={router} />replacesBrowserRouter+Routes.- A route object uses
Component(the component itself) orelement(a JSX element). Both work:{ path: '/', Component: Home }is the same as{ path: '/', element: <Home /> }. - Children go in a
childrenarray.
Why use the object form? It enables route-level features such as loader (fetch data before rendering), action (handle form submissions), errorElement and lazy (load code on demand). You will use them in Route Loaders and Lazy Routes.
Which mode should I choose?
- Start with declarative (
BrowserRouter) for small apps and learning. - Choose data mode when routes need to load data, handle forms or lazy-load code. Note that you must choose one at the top of your app, because
BrowserRouterandRouterProviderare alternatives. - For a server-rendered or file-based setup, consider framework mode or a different framework.
Hash and memory routers
Two other routers exist for special cases:
HashRouterkeeps the route after a#(/#/about). Use it only when you cannot make the server returnindex.html.MemoryRouterkeeps the location in memory, with no address bar. It is perfect for tests and non-browser environments; see Basic Testing Concepts.
Key points
- A route pairs a
pathwith anelement(orComponent). Useindexfor the default child,:namefor parameters and*for splats. - JSX routes and route objects describe the same thing.
- Use route objects with
createBrowserRouterwhen you want loaders, actions and lazy loading.