React.js has transformed how developers build web frontends, introducing modular, component-based architecture. But for complex applications—like dashboards for Lovable AI services or admin panels for Django-powered backends—routing is essential. Routing determines how users move between different screens or “pages” in a single-page application (SPA).
React Router is the de facto routing library for React.js. It allows your app to map URLs to components, providing navigation, history, route parameters, and more—all with a seamless, JavaScript-powered experience. In today’s microservices architectures, where frontend and backend are often decoupled, client-side routing becomes essential for scalability and user experience.
Routing is the mechanism that decides which user interface (component, view) to render based on the current URL. In classical web applications (like those you might build with Django), the backend returns a new HTML page for each URL. In SPAs built with React.js, routing is handled on the frontend; clicking links changes components dynamically, without reloading the entire page.
While React.js provides the foundation for UI rendering, it has no opinion about URL handling. React Router fills this gap, offering:
React Router provides several types of routers. A Router is a component that keeps the UI in sync with the URL. The two most common are:
Real-world trade-off: If you host your microservices UIs with static site hosts or CDN, and can’t configure server-side rewrites to support browser history, use HashRouter. Otherwise, prefer BrowserRouter for clean URLs.
// Basic Usage
import { BrowserRouter } from "react-router-dom";
function App() {
return (
<BrowserRouter>
{/* routes here */}
</BrowserRouter>
);
}
A Route defines which component to render for a given path (URL). The path prop supports static and dynamic parameters.
// Home.js and About.js are ordinary React components
import { Route, Routes } from "react-router-dom";
import Home from "./Home";
import About from "./About";
function AppRoutes() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
);
}
Dynamic routes are used for parameters:
<Route path="/users/:id" element={<UserProfile />} />
Traditional navigation uses the HTML <a href=""> tag, which reloads the entire page. In React.js, you want client-side navigation (no page reloads, just component swaps).
Link, but adds a styling hook when the link is “active.”// Navigation Links
import { Link, NavLink, useNavigate } from "react-router-dom";
function Navbar() {
const navigate = useNavigate();
return (
<nav>
<Link to="/about">About</Link>
<NavLink to="/dashboard" style={({ isActive }) => (isActive ? { color: "blue" } : undefined)}>
Dashboard
</NavLink>
<button onClick={() => navigate("/login")}>Login</button>
</nav>
)
}
Route parameters allow you to build URLs like /users/42 and extract “42” as a user ID. This is crucial for dashboard pages, profile views, or resource details.
// Route: /users/:id
import { useParams } from "react-router-dom";
function UserProfile() {
const { id } = useParams();
// Fetch user profile with the id param
return <div>User ID is {id}</div>;
}
Complex apps often need different layouts for different sections. You may want sidebar navigation on some pages but not others. Nested routes let you define routes inside other routes, organizing UIs into hierarchies.
// MainLayout.js
import { Outlet, Link } from "react-router-dom";
function MainLayout() {
return (
<div>
<nav><Link to="/profile">Profile</Link></nav>
<div>
<Outlet /> {/* Renders sub-route component */}
</div>
</div>
);
}
// In your route config:
<Route path="/dashboard" element={<MainLayout />}>
<Route path="profile" element={<ProfilePage />} />
<Route path="settings" element={<SettingsPage />} />
</Route>
Suppose you’re building a microservices-based dashboard for your Lovable AI startup. The Django backend handles authentication, metrics, and service APIs, while the React.js frontend provides a fluid, modern SPA experience. You need to route users to Login, Dashboard, Service Details, and User Profile.
/login, /dashboard, /services/:serviceId, /profile// App.js
import { BrowserRouter, Routes, Route } from "react-router-dom";
import LoginPage from "./LoginPage";
import DashboardLayout from "./DashboardLayout";
import ServiceDetail from "./ServiceDetail";
import ProfilePage from "./ProfilePage";
import DashboardHome from "./DashboardHome";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route path="/" element={<DashboardLayout />}>
<Route index element={<DashboardHome />} />
<Route path="services/:serviceId" element={<ServiceDetail />} />
<Route path="profile" element={<ProfilePage />} />
</Route>
{/* Optionally, add a 404 page */}
</Routes>
</BrowserRouter>
);
}
serviceId.useParams to grab serviceId and fetch details from the Django REST API.// ServiceDetail.js
import { useParams } from "react-router-dom";
import { useEffect, useState } from "react";
function ServiceDetail() {
const { serviceId } = useParams();
const [service, setService] = useState(null);
useEffect(() => {
fetch(`/api/services/${serviceId}/`)
.then(res => res.json())
.then(data => setService(data));
}, [serviceId]);
if (!service) return <div>Loading...</div>;
return (
<div>
<h1>{service.name}</h1>
<p>{service.description}</p>
</div>
);
}
Imagine a user visiting /services/123:
Route path "/services/:serviceId", extracts serviceId = 123.serviceId.In microservices architecture, especially with decoupled frontends and backends (like React.js + Django), React Router’s client-side navigation means your application is less dependent on backend template rendering. For scalability:
React.lazy with routes) to split code and only load what’s needed per route.React Router is essential for any React.js SPA, especially in microservices setups where a clear separation between Django backends and dynamic, lovable AI-powered frontends is the norm. You now understand core concepts—routes, navigation, parameters, layout nesting, and practical setup. You’ve seen concrete code implementations and how routes empower real-world dashboards.
The next steps:
useLoaderData and async data APIs from advanced routing solutions.With these basics, you’re equipped to build fast, intuitive navigation in your next microservices frontend—bridging React.js, Lovable AI features, and robust Django backends.
