Client-Side Routing

By Syncfusion®, Inc. · Last updated

Routing with React Router: BrowserRouter, Routes and Route, Link and NavLink, useNavigate, route and query parameters, nested and index routes, layouts and a Not Found page.

Introduction to Routing

Routing means showing a different page for each web address (URL). For example, /books shows the list of books, and /about shows the About page.

In a React app, routing happens in the browser. This is called client-side routing. When you click a link, React changes the address and swaps the component on the screen. The page does not reload.

Real-World Example

A bookshop app has the URLs /, /books and /books/42. React Router reads the URL and shows Home, BookList or BookDetails.

A user clicks a <Link to="/books/42">. The router changes the URL and shows the details of book 42 without a page reload. The user can bookmark this URL or share it.

Client-side routing: the address changes, and React shows a different component, without reloading the page

bookcorner.com/

bookcorner.com/books

bookcorner.com/about

<HomePage />

<BooksPage />

<AboutPage />

One page in the browser. Only the part that matches the address is swapped.

A React app is one HTML page. The router reads the URL and decides which component to show.

Setting Up React Router

React does not have routing built in. The most used routing library is React Router. Its package for websites is called react-router-dom.

Install it in your project with one command:

npm install react-router-dom

Then you import the parts you need from "react-router-dom", such as BrowserRouter, Routes, Route and Link. This lesson uses React Router version 6.

The code boxes on this page already have React Router installed. Each box shows a small address bar at the top of the preview, with Back and Forward buttons, so you can see the URL change.

BrowserRouter

BrowserRouter is the component that turns routing on. You wrap your whole app in it, once, usually in main.tsx or at the top of App.

import { BrowserRouter } from "react-router-dom";

createRoot(document.getElementById("root")!).render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
);

BrowserRouter keeps the app in step with the browser's address bar. It also makes the browser's Back and Forward buttons work.

All other router parts, such as Routes, Link and useNavigate, only work inside BrowserRouter.

The code boxes on this page cannot change your real address bar. So inside them, BrowserRouter keeps the address in memory, and draws a small address bar at the top of the preview. Your code is the same as in a real app.

Routes and Route Components

You list your pages with two components:

  • <Routes> — a container that holds all your routes. It shows only the one route that matches the URL.
  • <Route> — one page. path is the address, and element is the component to show.
<Routes>
  <Route path="/" element={<HomePage />} />
  <Route path="/books" element={<BooksPage />} />
  <Route path="/about" element={<AboutPage />} />
</Routes>

The URL is compared with each Route path. The matching Route's element is shown

/books the URL now

<Routes>

path="/"

path="/books"

path="/about"

<BooksPage /> shown

Routes looks for the Route whose path matches the URL, and shows its element.

Navigation with Link

<Link> makes a clickable link to another route. Use to for the address.

<Link to="/books">Books</Link>

Do not use a normal <a href="/books"> inside a React app. A normal link reloads the whole page, so all your state is lost. Link changes the page without reloading.

Click the links. The address bar at the top changes, and only the heading below the menu changes. The menu stays, because it is outside <Routes>.

Now press the ← Back button in the address bar. You go back to the page before, just like in a real browser.

NavLink

NavLink is a special Link that knows when its page is open. It gives itself the class active on the current page. You can use that class to highlight the menu item.

Click each menu item. The blue one is always the page you are on.

Look at end on the Home link. Without it, / would count as active on every page, because every address starts with /. end means: active only when the address is exactly /.

useNavigate Hook

Sometimes you want to change the page from code, not from a link. For example, go to a "Thank you" page after an order is placed.

useNavigate gives you a function, usually called navigate. Call it with an address.

const navigate = useNavigate();
navigate("/thank-you"); // go to this page
navigate(-1);           // go back one page

Click Place order. The code runs first (the console shows a message), and then navigate opens the thank-you page.

Use Link when the user clicks to go somewhere. Use navigate when your code decides to go somewhere, such as after a form is sent.

Route Parameters

A route parameter is a changing part of the address, such as the id of a book: /books/1, /books/2, /books/3.

You write one route with a : before the changing part. Then you read it with the useParams hook.

Route parameter: the path /books/:id matches /books/42, and useParams gives id = 42

/books/42 the URL

/books/:id the Route path

useParams() { id: "42" }

The :id part of the path catches any value, and useParams gives it to you.

Click a book. The address becomes /books/2, for example. BookDetails reads id with useParams, and finds the book with that id.

Look at this line:

const { id } = useParams();

The name id matches :id in the route path. A parameter is always text, so the ids in books.ts are text too: "2", not 2.

Query Parameters

Query parameters are extra settings at the end of the address, after a ?. For example: /search?q=habits&sort=price.

They are used for things like search words, filters and sorting. They do not change which route matches. You read and change them with useSearchParams.

Query parameters: the part after ? holds key=value pairs, read with useSearchParams /search?q=habits&sort=price path q = "habits" sort = "price" ? starts the list · & joins two pairs

Query parameters are optional settings after the ?. They do not change which Route matches.

Type in in the box. The address becomes /?q=in, and the list shows only matching books. Because the search is in the address, a user can copy the link and share the same search.

  • searchParams.get("q") reads the value of q. It gives null if there is no q, so ?? "" uses an empty text instead.
  • setSearchParams({ q: "..." }) changes the query part of the address.

Nested Routes

A nested route is a route inside another route. The child's path is added to the parent's path.

<Route path="/account" element={<AccountPage />}>
  <Route path="orders" element={<Orders />} />   {/* /account/orders */}
  <Route path="profile" element={<Profile />} /> {/* /account/profile */}
</Route>

The parent component decides where the child appears, with <Outlet />. Outlet is a placeholder. React Router puts the matching child component there.

Index Routes

An index route is the child that shows when the address is exactly the parent's path. It has index instead of a path.

<Route path="/account" element={<AccountPage />}>
  <Route index element={<AccountHome />} />      {/* /account */}
  <Route path="orders" element={<Orders />} />   {/* /account/orders */}
</Route>

Without an index route, the Outlet would be empty at /account.

Route Layouts

A layout route is a parent route that holds the parts every page shares, such as the header, menu and footer. The pages are its children, shown in the Outlet.

A layout route keeps the header and footer. The Outlet is the hole where the child page appears

Layout (stays the same)

Header · Home · Books · About

<Outlet />

Home page

Books page

About page

Footer

The child page changes inside the Outlet. The header and footer are not drawn again.

Click through the menu. The header and footer never change. Only the middle part changes:

  • At /, the index route of the layout shows "Home".
  • At /account, the index route of Account shows "Hello, Asha".
  • At /account/orders, the orders route shows inside Account, which shows inside Layout.

Notice that child paths have no / at the start: path="account", not path="/account". A child path is added to its parent's path.

Not Found Page

When the address matches no route, React shows nothing. To show a friendly message instead, add a route with path="*". The * matches any address that no other route matched.

Click Old offers link. No route has that path, so the * route shows the "Page not found" message.

Common mistakes

MistakeWhat you seeFix
Using Link or useNavigate outside BrowserRouterError: useHref() may be used only in the context of a <Router>Wrap the app in <BrowserRouter>
Using <a href> for pages inside the appThe page reloads and the state is lostUse <Link to>
Forgetting <Outlet /> in a parent routeThe child page never showsAdd <Outlet /> where the child should appear
Starting a child path with /The child does not match as expectedWrite path="orders", not path="/orders"
Forgetting end on the Home NavLinkHome is always highlightedAdd end to the / link
Comparing a route parameter with a numberThe item is not foundParameters are text: compare with "2", or use Number(id)
No * routeUnknown addresses show an empty pageAdd <Route path="*" element={<NotFound />} />

Check Yourself

Exercises

What to Remember

  • Wrap the app in BrowserRouter, list pages with Routes and Route, and move between them with Link, NavLink or useNavigate.
  • Read /books/:id with useParams, and ?q=... with useSearchParams.
  • Use a layout route with <Outlet /> for shared parts, index for the default child, and path="*" for a Not Found page.

Next: User Access Control