React · Routing & Data

React Router

A single-page app still needs real URLs: /products, /products/7, /cart. React Router maps URLs to components, so the back button, bookmarks and shared links all work.

Intermediate 6 min Lesson 21 of 42Examples target React 19 with Vite.
Before you start:Components
0/42 in React
On this page · 6 min · Intermediate

Learning objectives#

  • Define routes with createBrowserRouter
  • Build layouts with nested routes and <Outlet />
  • Navigate with Link, NavLink and useNavigate
  • Read URL and query parameters

Explanation#

Install react-router (v7). createBrowserRouter([...]) lists routes: { path: "/", element: <Layout />, children: [...] }. Render it with <RouterProvider router={router} />.

Nested routes share a layout: the parent renders the header and footer plus <Outlet /> where the matching child appears. { index: true } is the child for the parent’s own URL.

<Link to="/cart"> changes the URL without reloading the page. <NavLink> adds an active class for the current page. useNavigate() navigates from code, e.g. after saving.

Dynamic segments: path "products/:id"; read with const { id } = useParams() (always a string).

Query strings: const [searchParams, setSearchParams] = useSearchParams(); searchParams.get("q"). A path "*" catches unknown URLs for a 404 page.

On the server, configure a fallback so every URL returns index.html (see the deployment lesson).

Syntax#

JSX Illustrative
const router = createBrowserRouter([
  { path: '/', element: <Layout />, children: [
    { index: true, element: <Home /> },
    { path: 'products/:id', element: <ProductPage /> },
    { path: '*', element: <NotFound /> },
  ]},
]);
<RouterProvider router={router} />

Code example: A small shop with nested routes#

JSXmain.jsx Illustrative
import { createRoot } from 'react-dom/client';
import {
  createBrowserRouter, RouterProvider, Outlet, Link, NavLink,
  useParams, useNavigate, useSearchParams,
} from 'react-router';


const PRODUCTS = [{ id: '1', name: 'Pen', price: 20 }, { id: '2', name: 'Notebook', price: 60 }];


function Layout() {
  return (
    <>
      <nav>
        <NavLink to="/" end>Home</NavLink> | <NavLink to="/products">Products</NavLink>
      </nav>
      <main><Outlet /></main>
    </>
  );
}


function Home() {
  return <h1>Welcome to the shop</h1>;
}


function ProductList() {
  const [searchParams, setSearchParams] = useSearchParams();
  const q = searchParams.get('q') ?? '';
  const visible = PRODUCTS.filter(p => p.name.toLowerCase().includes(q.toLowerCase()));
  return (
    <>
      <input value={q} onChange={e => setSearchParams({ q: e.target.value })} aria-label="Search" />
      <ul>{visible.map(p => <li key={p.id}><Link to={`/products/${p.id}`}>{p.name}</Link></li>)}</ul>
    </>
  );
}


function ProductPage() {
  const { id } = useParams();
  const navigate = useNavigate();
  const product = PRODUCTS.find(p => p.id === id);
  if (!product) return <p>Product not found.</p>;
  return (
    <>
      <h2>{product.name} — ₹{product.price}</h2>
      <button onClick={() => navigate('/products')}>Back to list</button>
    </>
  );
}


function NotFound() {
  return <p>404 — page not found. <Link to="/">Go home</Link></p>;
}


const router = createBrowserRouter([
  {
    path: '/',
    element: <Layout />,
    children: [
      { index: true, element: <Home /> },
      { path: 'products', element: <ProductList /> },
      { path: 'products/:id', element: <ProductPage /> },
      { path: '*', element: <NotFound /> },
    ],
  },
]);


createRoot(document.getElementById('root')).render(<RouterProvider router={router} />);
Expected output
“/” shows the nav and “Welcome to the shop”. “/products” lists Pen and Notebook; typing in the search box updates the URL to /products?q=note and filters the list. Clicking Notebook opens /products/2 with “Notebook — ₹60” and a Back button. Any unknown URL shows the 404 message. The nav is shared by every page and the active link is highlighted.

This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.

Step-by-step explanation#

  1. The router lists one parent route (Layout) with four children.
  2. Layout renders the shared nav and an <Outlet /> where the child page appears.
  3. NavLink marks the current page as active; end makes “Home” active only on “/”.
  4. useSearchParams keeps the search text in the URL, so it can be bookmarked and shared.
  5. useParams reads :id from /products/2; useNavigate goes back to the list from code.
  6. path "*" catches every unknown URL.

Real-world use case#

An admin dashboard has /orders, /orders/:id, /customers and /settings under one layout with a sidebar. Support staff paste links like /orders/1042 into tickets, and they open the right page directly.

Common mistakes#

<a href> for internal links

A normal anchor reloads the whole app and loses state. Use <Link to>.

404 on refresh in production

The server looks for a real /products/2 file. Configure a fallback to index.html.

Treating params as numbers

useParams() always returns strings. Convert with Number(id) or compare as strings.

Best practices#

  • Shared layouts with nested routes and Outlet
  • Keep filters and pages in the URL (search params)
  • A catch-all 404 route
  • Lazy-load large pages per route

Remember this#

Route → element. Parent layout → <Outlet /> for the child.

<Link to> navigates without reloading.

useParams for /:id, useSearchParams for ?q=.

Practice exercise#

Your task: Add a route /orders/:orderId that shows "Order #<orderId>" and a link back to /orders.

Need a hint?
Add { path: "orders/:orderId", element: <OrderPage /> } and read useParams().orderId.
Show solution
JSX Illustrative
import { Link, useParams } from 'react-router';


export function OrderPage() {
  const { orderId } = useParams();
  return (
    <>
      <h2>Order #{orderId}</h2>
      <Link to="/orders">← All orders</Link>
    </>
  );
}
// In the router's children: { path: 'orders/:orderId', element: <OrderPage /> }

Mini quiz#

React Router quizMultiple choice Question 1 of 3

Where does a nested child route render inside its parent layout?

Score so far: 0/0

Want more? Practise all React MCQs · React interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.