Welcome back to the React Mastery Series!
In the previous article, we explored Custom Hooks in React and learned how reusable logic helps developers build scalable and maintainable applications.
Today, we will explore one of the most important concepts in modern frontend development:
React Routing
Almost every real-world React application contains multiple screens:
- Login
- Dashboard
- Profile
- Settings
- Reports
- Transactions
- Admin panels
But React applications are usually built as:
Single Page Applications (SPA)
So how do we navigate between different pages without refreshing the browser?
The answer is React Router
What is Client-Side Routing?
Traditional websites work like this:
User Clicks Link
|
↓
Browser Requests New HTML Page
|
↓
Server Sends Page
|
↓
Browser Reloads
Every navigation causes a full page refresh.
React Single Page Applications work differently:
User Clicks Link
|
↓
React Router Intercepts Request
|
↓
URL Changes
|
↓
React Loads Component
|
↓
No Page Refresh
This creates a smooth application experience.
What is React Router?
React Router is a library that enables navigation between different components based on the URL.
Example:
/login
/dashboard
/profile
/settings
Each URL maps to a React component.
Example:
/login
|
↓
Login Component
/dashboard
|
↓
Dashboard Component
Installing React Router
For a React application:
npm install react-router-dom
The package provides:
- BrowserRouter
- Routes
- Route
- Link
- Navigate
- useNavigate
- useParams
Setting Up BrowserRouter
The first step is wrapping your application.
Example:
import { BrowserRouter } from "react-router-dom";
import App from "./App";
ReactDOM.createRoot(document.getElementById("root")).render(
<BrowserRouter>
<App />
</BrowserRouter>,
);
Now React can manage browser navigation.
Creating Routes
Routes define which component should display for a URL.
Example:
import { Routes, Route } from "react-router-dom";
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
);
}
Now:
/login
renders:
<Login />
Understanding Route Components
Example:
<Route path="/profile" element={<Profile />} />;
Contains path and element
The URL path specifies the url appeared in browser
Example:
/profile
element
The component to render on visiting the path specified.
Example:
<Profile />
Navigation Using Link
Traditional HTML - causes a browser refresh.
<a href="/dashboard"> Dashboard </a>
React Router provides:
import { Link } from "react-router-dom";
<Link to="/dashboard">Dashboard</Link>
Benefits:
- No page refresh
- SPA behavior
- Better performance
Creating a Navigation Bar
Example:
function Navbar() {
return (
<nav>
<Link to="/">Home</Link>
<Link to="/dashboard">Dashboard</Link>
<Link to="/profile">Profile</Link>
</nav>
);
}
When users click:
Dashboard
React loads:
<Dashboard />
without refreshing.
Programmatic Navigation with useNavigate
Sometimes navigation happens after an action.
Examples:
- Successful login
- Logout
- Form submission
Example:
import { useNavigate } from "react-router-dom";
function Login() {
const navigate = useNavigate();
function handleLogin() {
// API success
navigate("/dashboard");
}
return <button onClick={handleLogin}>Login</button>;
}
Flow:
User Login
|
↓
API Success
|
↓
navigate("/dashboard")
|
↓
Dashboard Page
Route Parameters
Many applications need dynamic URLs.
Example:
/users/101
Here:
101
is dynamic.
React Router supports this using parameters.
Example:
<Route path="/users/:id" element={<UserDetails />} />
Reading Route Parameters
Using:
useParams()
Example:
import { useParams } from "react-router-dom";
function UserDetails() {
const { id } = useParams();
return <h2>User ID: {id}</h2>;
}
URL:
/users/101
Output:
User ID: 101
Real-World Example: Banking Application
Consider:
/accounts/12345
where:
12345
is the account number.
Route:
<Route path="/accounts/:accountId" element={<AccountDetails />} />
Component:
const { accountId }=useParams();
Now the application knows which account to display.
Nested Routes
Large applications often have sections inside sections.
Example:
Dashboard
|
├── Overview
├── Transactions
└── Profile
Routes:
<Route>
<Route path="/dashboard" element={<Dashboard />} >
<Route path="transactions" element={<Transactions />} />
<Route path="profile" element={<Profile />} />
</Routes>
URL:
/dashboard/transactions
renders:
Dashboard
+
Transactions
Outlet Component
Nested routes use:
<Outlet />
Example:
import { Outlet } from "react-router-dom";
function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
<Outlet />
</div>
);
}
The child route appears where Outlet exists.
Protected Routes
Enterprise applications often require authentication.
Example:
Users should access:
/dashboard
only after login.
Without authentication:
/dashboard
|
↓
Redirect
|
↓
/login
Creating ProtectedRoute
Example:
function ProtectedRoute({ children }) {
const isAuthenticated = true;
if (!isAuthenticated) {
return <Navigate to="/login" />;
}
return children;
}
Usage:
<Route
path="/dashboard"
element={
<ProtectedRoute>
<Dashboard />
</ProtectedRoute>
}
/>;
Real-World Authentication Flow
Enterprise applications usually follow:
User Opens Application
|
↓
Check Token
|
↓
Token Exists?
|
-------------
| |
Yes No
| |
Dashboard Login
React Router handles navigation decisions.
Lazy Loading Routes
Large applications should not load every page immediately.
Example:
const Dashboard = lazy(() => import("./Dashboard") );
Route:
<Suspense fallback="Loading...">
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
</Suspense>;
Benefits:
- Smaller initial bundle
- Faster startup
- Better performance
Route Organization in Enterprise Projects
A scalable structure:
src
├── routes
│ ├── AppRoutes.jsx
│ ├── ProtectedRoute.jsx
├── pages
│ ├── Login.jsx
│ ├── Dashboard.jsx
│ └── Profile.jsx
├── layouts
│ └── MainLayout.jsx
Real-World Banking Application Routing
Example:
/login
/dashboard
/accounts
/accounts/:id
/transactions
/profile
/settings
Flow:
Login
|
↓
Authentication Success
|
↓
Dashboard
|
├── Accounts
|
├── Transactions
|
└── Profile
This is the architecture used in many enterprise React applications.
Common Mistakes
1. Using Anchor Tags
Avoid:
<a href="/dashboard"> Dashboard </a>
Use:
<Link to="/dashboard"> Dashboard </Link>
2. Forgetting BrowserRouter
Without:
<BrowserRouter>
routing will not work.
3. Incorrect Nested Routes
Parent route must contain:
<Outlet />
otherwise child routes won't appear.
4. Loading All Pages at Startup
Large applications should use:
- lazy loading
- code splitting
Best Practices
- Keep routes centralized.
- Use lazy loading for large applications.
- Create reusable protected routes.
- Use meaningful URL structures.
- Avoid unnecessary route nesting.
- Separate page components from reusable components.
Key Takeaways
Today, we learned:
✅ React Router enables navigation in Single Page Applications.
✅ Routes map URLs to React components.
✅ Link provides SPA navigation without refresh.
✅ useNavigate enables programmatic navigation.
✅ useParams reads dynamic route values.
✅ Protected routes secure application pages.
✅ Lazy loading improves application performance.
Coming Next 🚀
In Day 20, we will explore:
Building Production-Ready React Applications – Project Structure and Architecture
We will learn:
- Scalable folder structure
- Component organization
- Feature-based architecture
- Separation of concerns
- API service layers
- Error handling
- Environment configuration
- Enterprise React project patterns
This will connect all the concepts we learned so far into a real-world production architecture.
Happy Coding! 🚀
Top comments (0)