Routing and Navigation

Plan: B2B Developer

Lesson 11 of 25 · 20 min

Introduction

In a traditional web application, browsing to a new URL triggers a new HTTP request, and the server returns a full HTML page.

The Buyer Portal is a single-page React application, meaning that all functionality runs in the browser; this includes navigating from one Buyer Portal page to another. No full page reload is required when the user moves from “Orders” to “Invoices,” only a re-rendering of appropriate page components. To support this, the app needs a client-side routing solution that:

  • Maps URL changes (or in-app “go to page” actions) to a React component structure.
  • Keeps the URL in sync so that browser navigation behavior and links still work.
  • Avoids full HTTP requests for in-app navigation, for maximum performance.

React Router

React Router is one of the most popular, fully featured solutions for client-side routing. It keeps the UI in sync with the URL by matching the current location to a set of route definitions and rendering the corresponding components. Key concepts:

  • Routes: A route matches a URL pattern with a top-level page component.
  • Initial Loading: When a user initially browses to a URL, the router examines the client-side pattern and renders the right component structure.
  • Navigation: React Router provides a programmatic way to navigate to different routes, triggering re-rendering without fetching a new page from the server.

React Router makes several styles of router available. HashRouter is the router used by the Buyer Portal. With this router, the “hash” portion of a URL represents the Buyer Portal page:

https://mystore.com/garden/#/orders
https://mystore.com/garden/#/invoice

Everything after the # in the URL is ignored by the server in full page requests, but is used in the browser to determine the current Buyer Portal page.

The router supports nesting routes, with parent routes representing earlier segments of the URL path (such as a top-level / route), and their components wrapping child routes. The following is a simple demonstration of an app implementing HashRouter for paths like the above:

import { HashRouter, Routes, Route } from 'react-router-dom';
function App() {
return (
<HashRouter>
<Routes>
<Route path="/" element={<ExampleTopComponent />} />
<Route path="/orders" element={<ExampleOrdersComponent />} />
<Route path="/invoice" element={<ExampleInvoiceComponent />} />
</Route>
</Routes>
</HashRouter>
);
}

Note that in the full context of a BigCommerce storefront, the portion of the URL before the # does determine the server-side page that is initially rendered. (For example, a catalog page.) The URL path /garden/#/orders might indicate the shopper browsed to a Garden category page before opening the Buyer Portal, after which client-side routing takes over. The paths /garden/#/orders and /kitchen/#/orders will render different initial server-side pages, but the Buyer Portal content will be identical.


React Router in the Buyer Portal

All file paths referenced in these exercises are relative to apps/storefront/src in your Buyer Portal project.

The low-level details of the React Router implementation are taken care of by built-in layout in the Buyer Portal. To add or customize routes, it is typically only necessary to modify the portal’s own configuration files. These source files are involved:

  • App.tsx: Renders <HashRouter>
  • components/layout/B3RenderRouter.tsx: Renders all <Route> components based on config
  • shared/routeList.ts and shared/routes/index.tsx: The central routes configuration

You’ll see more of the details in the exercise to come.

Permissions

In the Buyer Portal, we need to be concerned not only with routing itself, but with a user’s permissions to access a particular route.

There are two important concepts for company user authorization:

  • Users have different roles. Built-in roles include Admin, Senior Buyer, and Junior Buyer. It’s possible to create custom roles in your own store.
  • A role has one or more permissions. Permissions represent the specific actions that a user can perform, including the ability to view certain content.

Part of a route’s configuration includes both role-based and permission-based details about who can access the route. You’ll be modifying details in shared/routes/config.ts in the next exercise.

It’s not appropriate to use typical <a> elements to navigate between pages in a single-page application. While a link to /current-page/#/orders will result in the correct content being rendered, the round trip to the server to render the new URL from scratch is unnecesssary.

The Buyer Portal makes the utility function setOpenPage available to all page components for the purpose of client-side navigation. This function accepts parameters to control the portal’s open state and a Buyer Portal URL path to navigate to.

Resources