No history yet

Configuring Router Objects

A New Way to Route

In older versions of React Router, you defined your application's routes using JSX components like <BrowserRouter>, <Routes>, and <Route>. While this worked, it had limitations, especially when it came to loading data for your pages.

The modern approach in React Router v6+ uses plain JavaScript objects to define your routes. This change unlocks powerful new features, including the ability to load data before your component renders, leading to a much smoother user experience.

Configuring Your Router

Instead of wrapping your application in a <BrowserRouter> component, you now create a router instance using a function called createBrowserRouter. This function takes an array of route objects, where each object defines a path and the component to render for that path.

// In a file like router.js
import { createBrowserRouter } from 'react-router-dom';
import RootLayout from './routes/RootLayout';
import HomePage from './pages/HomePage';
import AboutPage from './pages/AboutPage';

const router = createBrowserRouter([
  {
    path: "/",
    element: <RootLayout />,
    children: [
      { index: true, element: <HomePage /> },
      { path: "about", element: <AboutPage /> },
    ],
  },
]);

export default router;

Notice the children property. This is how you create nested layouts. In this example, HomePage and AboutPage will be rendered inside the RootLayout component.

Once you have your router configuration, you provide it to your application's root using the <RouterProvider> component. This is typically done in your main.jsx or index.js file.

// In your main.jsx or index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { RouterProvider } from 'react-router-dom';
import router from './router'; // Import the router you just created

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>
);

The key takeaway: You define your routes as a data structure and then pass that structure to a <RouterProvider> at the top level of your app.

Why the Object-Based Approach?

This new object-based API isn't just a different style; it's a fundamental shift that enables better performance. The main benefit is solving the common problem of data loading "waterfalls."

Previously, a component would have to render first, and only then could it trigger a data fetch, often showing a loading spinner. With the new API, you can define loader functions directly on your route objects. React Router can then start fetching data for the next page as soon as the user clicks a link, even before the new page's code has loaded. This means by the time your component renders, its data is often already there.

Lesson image

This leads to a "fetch-then-render" pattern, which is a significant improvement over the old "render-then-fetch" method. Here's a glimpse of what that looks like in the route configuration:

// Example of a route with a data loader
{
  path: "/products/:productId",
  element: <ProductDetails />,
  loader: async ({ params }) => {
    // This function runs BEFORE the component renders
    return fetch(`/api/products/${params.productId}`);
  },
}

By defining data needs alongside routes, React Router can fetch data before rendering the component, eliminating loading spinners and improving user experience.

Browser vs. Hash

You'll primarily use createBrowserRouter, which uses the browser's History API to keep your UI in sync with the URL. This results in clean URLs like myapp.com/products.

However, there's also createHashRouter. This version uses the hash (#) portion of the URL to manage routing, resulting in URLs like myapp.com/#/products. This is useful for older web servers that can't be configured to handle client-side routing or for some specific hosting environments like GitHub Pages.

FeaturecreateBrowserRoutercreateHashRouter
URL Formatexample.com/pageexample.com/#/page
Server SetupRequires server configuration to handle all paths.Works out-of-the-box on any static file server.
Best ForMost modern web applications.Static site hosting, legacy servers.

For most new projects, createBrowserRouter is the correct choice. It provides a better user experience with cleaner, more standard URLs.

Quiz Questions 1/4

What is the primary way to define routes in modern React Router (v6+)?

Quiz Questions 2/4

After creating a router instance with createBrowserRouter, which component do you use to provide it to your React application?

Adopting the object-based routing configuration is the modern way to build with React Router. It not only simplifies route management but also unlocks powerful data-loading patterns that are essential for building fast, user-friendly applications.