Centralized Route Configuration
The useRoutes hook enables a configuration-based approach to routing in React, allowing developers to define routes in a JavaScript array rather than JSX.
Basic Setup without Lazy Loading
Create a dedicated configuration file to define path mappings and associated components.
// config/router.js
import { Navigate } from "react-router-dom";
import Dashboard from "../views/Dashboard";
import Profile from "../views/Profile";
import Inventory from "../views/Inventory";
import ItemDetails from "../views/Inventory/ItemDetails";
import Reviews from "../views/Inventory/Reviews";
const routeConfig = [
{
path: "/",
element: <Navigate to="/dashboard" />,
},
{
path: "/dashboard",
element: <Dashboard />,
},
{
path: "/profile",
element: <Profile />,
},
{
path: "/inventory",
element: <Inventory />,
children: [
{
path: "details",
element: <ItemDetails />,
},
{
path: "reviews",
element: <Reviews />
}
],
},
];
export default routeConfig;
In the root component, invoke useRoutes with the configuration array.
// App.jsx
import { Link, useRoutes } from "react-router-dom";
import routeConfig from "./config/router";
function App() {
const routing = useRoutes(routeConfig);
return (
<>
<nav>
<Link to="/dashboard">Dashboard</Link> |
<Link to="/profile">Profile</Link> |
<Link to="/inventory">Inventory</Link>
</nav>
<hr />
{routing}
>
);
}
export default App;
The entry point must wrap the application in BrowserRouter.
// main.jsx
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import App from "./App";
ReactDOM.createRoot(document.getElementById("root")).render(
<BrowserRouter>
<App />
</BrowserRouter>
);
Implementing Nested Routes
Parent components containing child routes must utilize the Outlet component to render the matched child view.
// views/Inventory.jsx
import React from "react";
import { Outlet, Link } from "react-router-dom";
export default function Inventory() {
return (
<>
<h2>Inventory Management</h2>
<div>
<Link to="/inventory/details">Item Details</Link> |
<Link to="/inventory/reviews">Reviews</Link>
</div>
<hr />
<Outlet />
>
);
}
Optimizing with Code Splitting
To reduce initial bundle size, components can be loaded on-demand using React.lazy. Since lazy-loaded components render asynchronously, they must be wrapped in Suspense to provide a fallback UI during loading.
A utility function can encapsulate this logic to keep the route configuration clean.
// config/router.js
import React from "react";
import { Navigate } from "react-router-dom";
// Helper to wrap lazy components with Suspense
const createLazyRoute = (componentPath) => {
const LazyComponent = React.lazy(() => import(`../views/${componentPath}`));
return (
<LazyComponent />
);
};
export default [
{
path: "/",
element: <Navigate to="/dashboard" />,
},
{
path: "/dashboard",
element: createLazyRoute("Dashboard"),
},
{
path: "/profile",
element: createLazyRoute("Profile"),
},
{
path: "/inventory",
element: createLazyRoute("Inventory"),
children: [
{
path: "details",
element: createLazyRoute("Inventory/ItemDetails"),
},
{
path: "reviews",
element: createLazyRoute("Inventory/Reviews"),
}
],
},
];