Design Converter
Education
Last updated on Mar 28, 2025
•14 mins read
Last updated on Mar 20, 2025
•14 mins read
When building a complex React app, setting up the React Router Base Path correctly can significantly improve your routing architecture and overall application performance.
This blog helps you understand how to structure your routes effectively, particularly when working with nested paths and sub-directories.
React Router is the standard routing library for React applications. It keeps your UI in sync with the URL by handling route changes and rendering the appropriate components. Before we dive into base path configurations, let's review the core concepts of React Router.
At its core, React Router matches a URL to a specific component hierarchy. When a user navigates to a different path, the React Router determines which component should be rendered based on the route path definition.
To use React Router in your project, you need to import the necessary components from the React Router dom package:
1import { BrowserRouter, Routes, Route } from 'react-router-dom'; 2import React from 'react';
The React Router library provides several router implementations. The most common is BrowserRouter, which uses HTML5 history API to keep the UI in sync with the URL.
The base path (or basename) property is a powerful configuration option in React Router that sets the base URL for all locations. When your React app is served from a sub-directory rather than the root, configuring the base path becomes necessary.
The base path is the starting segment of your URL path that remains consistent across your entire application. It acts as a prefix to all routes within your React Router configuration.
For example, if your app is hosted at https://example.com/my-app/
, then /my-app
would be your base path.
Proper configuration of the base path requires understanding how to set up the BrowserRouter component with the correct basename property.
To configure the base path in React Router DOM, you need to specify the basename property when creating your router:
1import { BrowserRouter, Routes, Route } from 'react-router-dom'; 2import React from 'react'; 3import App from './App'; 4import Dashboard from './components/Dashboard'; 5import Profile from './components/Profile'; 6 7function Main() { 8 return ( 9 <BrowserRouter basename="/my-app"> 10 <Routes> 11 <Route path="/" element={<App />} /> 12 <Route path="/dashboard" element={<Dashboard />} /> 13 <Route path="/profile" element={<Profile />} /> 14 </Routes> 15 </BrowserRouter> 16 ); 17} 18 19export default Main;
In this example, all routes will be prefixed with "/my-app
". When you navigate to "/dashboard
", the actual URL will be "/my-app/dashboard
".
A properly formatted basename should always include a leading slash. The React Router expects the basename to be formatted correctly to avoid potential routing issues:
1// Correct 2<BrowserRouter basename="/admin"> 3 4// Incorrect - missing leading slash 5<BrowserRouter basename="admin">
While a leading slash is required, you should not include a trailing slash in your base path:
1// Correct 2<BrowserRouter basename="/admin"> 3 4// Incorrect - includes trailing slash 5<BrowserRouter basename="/admin/">
Including a trailing slash can create issues with path matching and URL generation.
The history object is a core component of React Router that tracks navigation history. When configuring a base path, the history object automatically adjusts to account for the base path prefix.
In some cases, you might need to create and configure your history object:
1import { createBrowserHistory } from 'history'; 2import { Router, Routes, Route } from 'react-router-dom'; 3import React from 'react'; 4 5// Create custom browser history with base path 6const history = createBrowserHistory({ 7 basename: '/my-app' 8}); 9 10function CustomRouterApp() { 11 return ( 12 <Router history={history}> 13 <Routes> 14 <Route path="/" element={<Home />} /> 15 <Route path="/about" element={<About />} /> 16 </Routes> 17 </Router> 18 ); 19}
The history object provides several methods to programmatically navigate between routes.
Let's look at some practical examples of how to implement base paths in various scenarios.
1import React from 'react'; 2import { BrowserRouter, Routes, Route } from 'react-router-dom'; 3import Home from './components/Home'; 4import About from './components/About'; 5import Contact from './components/Contact'; 6 7function App() { 8 return ( 9 <BrowserRouter basename="/blog"> 10 <Routes> 11 <Route path="/" element={<Home />} /> 12 <Route path="/about" element={<About />} /> 13 <Route path="/contact" element={<Contact />} /> 14 </Routes> 15 </BrowserRouter> 16 ); 17} 18 19export default App;
In this example, the base route is "/blog
", so the actual routes will be:
• Home: /blog/
• About: /blog/about
• Contact: /blog/contact
You may design more intricate routing systems using React Router's support for nested routes.When using a base path, all child routes also inherit the base path prefix.
1import React from 'react'; 2import { BrowserRouter, Routes, Route } from 'react-router-dom'; 3import Dashboard from './components/Dashboard'; 4import DashboardHome from './components/DashboardHome'; 5import Analytics from './components/Analytics'; 6import Settings from './components/Settings'; 7 8function App() { 9 return ( 10 <BrowserRouter basename="/admin"> 11 <Routes> 12 <Route path="/" element={<Dashboard />}> 13 <Route index element={<DashboardHome />} /> 14 <Route path="analytics" element={<Analytics />} /> 15 <Route path="settings" element={<Settings />} /> 16 </Route> 17 </Routes> 18 </BrowserRouter> 19 ); 20} 21 22export default App;
The nested routes structure can be visualized as follows:
As your application grows, you might need more advanced configurations for your routing system.
In some cases, you might need to determine the base path dynamically based on the deployment environment or other factors:
1import React from 'react'; 2import { BrowserRouter, Routes, Route } from 'react-router-dom'; 3 4function App() { 5 // Determine base path based on environment 6 const getBasename = () => { 7 if (process.env.NODE_ENV === 'development') { 8 return '/'; 9 } 10 return '/production-app'; 11 }; 12 13 return ( 14 <BrowserRouter basename={getBasename()}> 15 <Routes> 16 <Route path="/" element={<Home />} /> 17 <Route path="/dashboard" element={<Dashboard />} /> 18 </Routes> 19 </BrowserRouter> 20 ); 21} 22 23export default App;
When you need to match a path exactly, you can use the end property in the Routes component along with your base path:
1import React from 'react'; 2import { BrowserRouter, Routes, Route } from 'react-router-dom'; 3 4function App() { 5 return ( 6 <BrowserRouter basename="/app"> 7 <Routes> 8 <Route path="/" element={<Home />} /> 9 {/* This will only match /app/products exactly */} 10 <Route path="/products" element={<ProductsList />} end /> 11 {/* This will match any path under /app/products/, like /app/products/123 */} 12 <Route path="/products/:id" element={<ProductDetail />} /> 13 </Routes> 14 </BrowserRouter> 15 ); 16}
The Link component from React Router Dom automatically handles base paths, but it's important to understand how it works.
When using the Link component, you don't need to include the base path in your to prop. React Router will automatically add the base path:
1import { Link } from 'react-router-dom'; 2import React from 'react'; 3 4function Navigation() { 5 return ( 6 <nav> 7 <Link to="/">Home</Link> 8 <Link to="/about">About</Link> 9 <Link to="/contact">Contact</Link> 10 </nav> 11 ); 12}
If your BrowserRouter has a basename of "/app", these links will point to:
• Home: /app/
• About: /app/about
• Contact: /app/contact
When linking to external resources or other parts of your website not managed by React Router, you need to use regular anchor tags:
1import { Link } from 'react-router-dom'; 2import React from 'react'; 3 4function Navigation() { 5 return ( 6 <nav> 7 {/* Internal links handled by React Router */} 8 <Link to="/dashboard">Dashboard</Link> 9 10 {/* External link */} 11 <a href="https://example.com">External Site</a> 12 13 {/* Link to another app on the same domain not using the current base path */} 14 <a href="/different-app/page">Different App</a> 15 </nav> 16 ); 17}
Redirects are an important part of routing, and they need special attention when using a base path.
The Navigate component from React Router v6 handles base paths automatically:
1import { Routes, Route, Navigate } from 'react-router-dom'; 2import React from 'react'; 3 4function AppRoutes() { 5 return ( 6 <Routes> 7 <Route path="/old-page" element={<Navigate to="/new-page" replace />} /> 8 <Route path="/new-page" element={<NewPage />} /> 9 </Routes> 10 ); 11}
If your app has a base path of "/app
", this will redirect from "/app/old-page
" to "/app/new-page
".
You can also navigate programmatically using the useNavigate hook:
1import { useNavigate } from 'react-router-dom'; 2import React from 'react'; 3 4function RedirectButton() { 5 const navigate = useNavigate(); 6 7 const handleClick = () => { 8 navigate('/dashboard'); 9 }; 10 11 return ( 12 <button onClick={handleClick}> 13 Go to Dashboard 14 </button> 15 ); 16}
When using a base path, the navigate function automatically handles the base path prefix.
When implementing server-side rendering with React Router, you need to configure your base path on both the client and server.
For server-side rendering, React Router provides the StaticRouter component:
1// Server code 2import { StaticRouter } from 'react-router-dom/server'; 3import { renderToString } from 'react-dom/server'; 4import React from 'react'; 5import App from './App'; 6 7export function renderApp(req, res) { 8 const context = {}; 9 const html = renderToString( 10 <StaticRouter location={req.url} basename="/app" context={context}> 11 <App /> 12 </StaticRouter> 13 ); 14 15 // Handle redirects 16 if (context.url) { 17 res.redirect(context.url); 18 return; 19 } 20 21 res.send(` 22 <!DOCTYPE html> 23 <html> 24 <head> 25 <title>My App</title> 26 </head> 27 <body> 28 <div id="root">${html}</div> 29 <script src="/static/bundle.js"></script> 30 </body> 31 </html> 32 `); 33}
It's crucial to use the same base path configuration on both the client and server to avoid routing mismatches:
1// Client code 2import { BrowserRouter } from 'react-router-dom'; 3import { hydrateRoot } from 'react-dom/client'; 4import React from 'react'; 5import App from './App'; 6 7hydrateRoot( 8 document.getElementById('root'), 9 <BrowserRouter basename="/app"> 10 <App /> 11 </BrowserRouter> 12);
Common issues with base paths can be challenging to diagnose. Here are some strategies to help identify and fix these problems.
Missing leading slash: Always ensure your base path starts with a slash.
Included trailing slash: Avoid trailing slashes in your base path.
Inconsistent base paths: Ensure the same base path is used across your entire application.
Case sensitivity: Base paths can be case sensitive depending on your server configuration.
React Router Dev Tools: These browser extensions help visualize your current route and route configurations.
Browser Developer Console: Check for any routing-related errors in the console.
Network Tab: Monitor network requests to see if the correct URLs are being requested.
1// Debug utility to log current location with base path info 2import { useLocation } from 'react-router-dom'; 3import React from 'react'; 4 5function RouteDebugger() { 6 const location = useLocation(); 7 8 console.log('Current location:', { 9 pathname: location.pathname, 10 search: location.search, 11 hash: location.hash, 12 state: location.state, 13 }); 14 15 return null; // This component doesn't render anything 16} 17 18// Add this component to your app 19function App() { 20 return ( 21 <> 22 <RouteDebugger /> 23 {/* Rest of your app */} 24 </> 25 ); 26}
To make the most of React Router's base path feature, follow these best practices:
1// config.js 2export const APP_BASE_PATH = '/dashboard'; 3 4// In your router setup 5import { APP_BASE_PATH } from './config'; 6import { BrowserRouter } from 'react-router-dom'; 7import React from 'react'; 8 9function App() { 10 return ( 11 <BrowserRouter basename={APP_BASE_PATH}> 12 {/* Routes */} 13 </BrowserRouter> 14 ); 15}
1import { Routes, Route } from 'react-router-dom'; 2import React from 'react'; 3 4// User-related routes 5function UserRoutes() { 6 return ( 7 <Route path="users"> 8 <Route index element={<UsersList />} /> 9 <Route path=":id" element={<UserProfile />} /> 10 <Route path="settings" element={<UserSettings />} /> 11 </Route> 12 ); 13} 14 15// Main routes configuration 16function AppRoutes() { 17 return ( 18 <Routes> 19 <Route path="/" element={<Home />} /> 20 {UserRoutes()} 21 <Route path="*" element={<NotFound />} /> 22 </Routes> 23 ); 24}
React.lazy()
to split your code based on routes.1import React, { Suspense, lazy } from 'react'; 2import { BrowserRouter, Routes, Route } from 'react-router-dom'; 3 4// Lazy load components 5const Home = lazy(() => import('./components/Home')); 6const Dashboard = lazy(() => import('./components/Dashboard')); 7const Settings = lazy(() => import('./components/Settings')); 8 9function App() { 10 return ( 11 <BrowserRouter basename="/app"> 12 <Suspense fallback={<div>Loading...</div>}> 13 <Routes> 14 <Route path="/" element={<Home />} /> 15 <Route path="/dashboard" element={<Dashboard />} /> 16 <Route path="/settings" element={<Settings />} /> 17 </Routes> 18 </Suspense> 19 </BrowserRouter> 20 ); 21} 22 23export default App;
React.memo
and shouldComponentUpdate to prevent unnecessary re-renders when routes change.React Router has evolved, and the base path implementation varies between versions.
React Router v6 introduced significant changes to the API, including how base paths are handled:
1// React Router v6 2import { BrowserRouter, Routes, Route } from 'react-router-dom'; 3import React from 'react'; 4 5function App() { 6 return ( 7 <BrowserRouter basename="/app"> 8 <Routes> 9 <Route path="/" element={<Home />} /> 10 <Route path="/about" element={<About />} /> 11 </Routes> 12 </BrowserRouter> 13 ); 14}
In React Router v5, the implementation is slightly different:
1// React Router v5 2import { BrowserRouter, Switch, Route } from 'react-router-dom'; 3import React from 'react'; 4 5function App() { 6 return ( 7 <BrowserRouter basename="/app"> 8 <Switch> 9 <Route exact path="/" component={Home} /> 10 <Route path="/about" component={About} /> 11 </Switch> 12 </BrowserRouter> 13 ); 14}
Note the differences:
• V5 uses Switch instead of Routes
• V5 uses component prop instead of element
• V5 requires the exact prop to match paths exactly
Child routes work well with base paths, creating a hierarchy of routes that all inherit the base path prefix.
1import { BrowserRouter, Routes, Route, Outlet } from 'react-router-dom'; 2import React from 'react'; 3 4function Dashboard() { 5 return ( 6 <div> 7 <h1>Dashboard</h1> 8 <nav> 9 <Link to="">Overview</Link> 10 <Link to="stats">Statistics</Link> 11 <Link to="settings">Settings</Link> 12 </nav> 13 <Outlet /> {/* Child components render here */} 14 </div> 15 ); 16} 17 18function App() { 19 return ( 20 <BrowserRouter basename="/admin"> 21 <Routes> 22 <Route path="/" element={<Home />} /> 23 <Route path="dashboard" element={<Dashboard />}> 24 <Route index element={<DashboardOverview />} /> 25 <Route path="stats" element={<DashboardStats />} /> 26 <Route path="settings" element={<DashboardSettings />} /> 27 </Route> 28 </Routes> 29 </BrowserRouter> 30 ); 31}
In this example, the complete URL structure would be:
• Home: /admin/
• Dashboard Overview: /admin/dashboard/
• Dashboard Stats: /admin/dashboard/stats
• Dashboard Settings: /admin/dashboard/settings
Different deployment scenarios may require different base path configurations.
When deploying to GitHub Pages, your app is typically served from a sub-directory:
1import { BrowserRouter } from 'react-router-dom'; 2import React from 'react'; 3function App() { 4 return ( 5 <BrowserRouter basename="/repo-name"> 6 {/* Routes */} 7 </BrowserRouter> 8 ); 9}
When serving your app from an Nginx sub-directory:
1import { BrowserRouter } from 'react-router-dom'; 2import React from 'react'; 3 4function App() { 5 return ( 6 <BrowserRouter basename="/web-app"> 7 {/* Routes */} 8 </BrowserRouter> 9 ); 10}
Additionally, you'll need to configure Nginx to properly handle the routes:
1server { 2 listen 80; 3 server_name example.com; 4 5 location /web-app { 6 try_files $uri $uri/ /web-app/index.html; 7 } 8}
Getting comfortable with the React Router base path makes building React apps easier and more organized. Understanding how to set up and adjust the base URL helps keep the app flexible and easier to manage. It also makes deploying across different environments smoother. Keep practicing, and working with routes will soon feel natural.
When implementing routing in your React app, remember these key points:
Always include a leading slash in your base path
Avoid trailing slashes in your base path configuration
Use the same base path consistently throughout your application
Let the Link component handle base path prefixing automatically
Consider different deployment scenarios when planning your routing structure
With these techniques, you'll be able to build robust applications with efficient routing systems that provide a smooth user experience regardless of the deployment environment.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.