React Router Dom - Routes, React Router Hooks, Navigation and Protected Routes
react-router-dom
React Router is a powerful library for handling routing in React applications. It provides a declarative way to define routes and manage navigation. Here’s a detailed guide:
Setting Up React Router
npm install react-router-dom
Routes
& Route
Routes
and Route
components are used to define the routing logic in your application.
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from './Home';
import About from './About';
import Contact from './Contact';
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
<Route path="contact" element={<Contact />} />
</Routes>
</Router>
);
}
export default App;
Nested Routes
Nested routes allow you to define routes within other routes, which is useful for hierarchical navigation.
import React from 'react';
import { BrowserRouter as Router, Routes, Route, Outlet } from 'react-router-dom';
// These can be a saperate components.
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
<Outlet /> {/* Render nested routes here */}
</div>
);
}
function Profile() {
return <h3>Profile</h3>;
}
function Settings() {
return <h3>Settings</h3>;
}
// Inside of our App component.
function App() {
return (
<Router>
<Routes>
<Route path="dashboard" element={<Dashboard />}>
<Route path="profile" element={<Profile />} />
<Route path="settings" element={<Settings />} />
</Route>
</Routes>
</Router>
);
}
export default App;
React Router Hooks
useLocation
import React from 'react';
import { useLocation } from 'react-router-dom';
function ShowLocation() {
const location = useLocation();
return (
<div>
<h3>Current Location</h3>
<Link to={`${location.pathname}/newpath`}>New path</Link>
</div>
);
}
export default ShowLocation;
useParams
The useParams
hook returns an object of key-value pairs of the dynamic params from the current URL that were matched by the Route
.
import React from 'react';
import { useParams } from 'react-router-dom';
function UserProfile() {
const { userId } = useParams();
return (
<div>
<h3>User ID: {userId}</h3>
</div>
);
}
export default UserProfile;
Outlet
The Outlet
component is used to render the child routes in a nested route structure. It serves as a placeholder for where the nested content should be rendered.
Link
The Link
component is used for navigation. It renders an anchor (<a>
) element that links to a different route.
import React from 'react';
import { Link } from 'react-router-dom';
function Navigation() {
return (
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/contact">Contact</Link>
</li>
</ul>
</nav>
);
}
export default Navigation;
NavLink
NavLink
is similar to Link
but provides additional styling attributes to the link when it matches the current URL.
import React from 'react';
import { NavLink } from 'react-router-dom';
function Navigation() {
return (
<nav>
<ul>
<li>
<NavLink to="/" end activeClassName="active">Home</NavLink>
</li>
<li>
<NavLink to="/about" activeClassName="active">About</NavLink>
</li>
<li>
<NavLink to="/contact" activeClassName="active">Contact</NavLink>
</li>
</ul>
</nav>
);
}
export default Navigation;
Redirects
The Navigate
component is used to programmatically navigate to a different route, similar to redirect
.
import React from 'react';
import { Routes, Route, Navigate } from 'react-router-dom';
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="old-path" element={<Navigate to="/new-path" />} />
<Route path="new-path" element={<NewComponent />} />
</Routes>
);
}
export default App;
Programmatic Navigation
The useNavigate
hook allows for programmatic navigation.
import React from 'react';
import { useNavigate } from 'react-router-dom';
function Home() {
const navigate = useNavigate();
const goToAbout = () => {
navigate('/about');
};
return (
<div>
<button onClick={goToAbout}>Go to About</button>
</div>
);
}
export default Home;
React Router is a powerful library for managing navigation and routing in React applications.
Basic Routing: Using
Route
andRoutes
to define paths.Nested Routes: Organizing hierarchical routes using
Outlet
.Hooks: Utilizing
useLocation
,useParams
, anduseNavigate
for accessing route data and programmatic navigation.Linking: Using
Link
andNavLink
for navigation.Redirection: Using
Navigate
for redirects.
These features make React Router a flexible and efficient tool for handling complex routing scenarios in React applications.
Navigation
The useNavigate
hook in React Router allows for programmatic navigation within a React application. This is useful for scenarios where you need to navigate to a different route as a result of an event, such as a button click, form submission, or after an API call.
import React from 'react';
import { BrowserRouter as Router, Routes, Route, useNavigate } from 'react-router-dom';
function Home() {
const navigate = useNavigate();
const goToAbout = () => {
navigate('/about');
};
return (
<div>
<h1>Home Page</h1>
<button onClick={goToAbout}>Go to About</button>
</div>
);
}
function About() {
return <h1>About Page</h1>;
}
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Routes>
</Router>
);
}
export default App;
Passing State with Navigation
You can pass state to the new route using useNavigate
. This state can be accessed in the destination component.
// Home Component
function Home() {
const navigate = useNavigate();
const goToAbout = () => {
navigate('/about', { state: { fromHome: true } });
};
return (
<div>
<h1>Home Page</h1>
<button onClick={goToAbout}>Go to About</button>
</div>
);
}
// About Component
import { useLocation } from 'react-router-dom';
function About() {
const location = useLocation();
const fromHome = location.state?.fromHome;
return (
<div>
<h1>About Page</h1>
{fromHome && <p>Navigated from Home Page</p>}
</div>
);
}
Navigating Back and Forward
useNavigate
can also be used to navigate back and forward in the history stack.
function NavigationExample() {
const navigate = useNavigate();
return (
<div>
<button onClick={() => navigate(-1)}>Go Back</button>
<button onClick={() => navigate(1)}>Go Forward</button>
</div>
);
}
Replace the Current Entry
To replace the current entry in the history stack, you can use the replace
option. This is useful when you don't want the user to go back to the previous route.
function Home() {
const navigate = useNavigate();
const goToAbout = () => {
navigate('/about', { replace: true });
};
return (
<div>
<h1>Home Page</h1>
<button onClick={goToAbout}>Go to About</button>
</div>
);
}
Navigation with Dynamic Parameters
You can navigate to a route with dynamic parameters using useNavigate
.
function Home() {
const navigate = useNavigate();
const goToUser = (userId) => {
navigate(`/user/${userId}`);
};
return (
<div>
<h1>Home Page</h1>
<button onClick={() => goToUser(1)}>Go to User 1</button>
<button onClick={() => goToUser(2)}>Go to User 2</button>
</div>
);
}
function User() {
const { userId } = useParams();
return (
<div>
<h1>User Page</h1>
<p>User ID: {userId}</p>
</div>
);
}
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="user/:userId" element={<User />} />
</Routes>
</Router>
);
}
export default App;
Basic Navigation: Use
useNavigate
to navigate to a new route programmatically.Passing State: Pass state to the new route using the
state
option.History Navigation: Use negative anAuthentication Contextd positive integers to navigate back and forward in the history stack.
Replace Option: Use
replace: true
to replace the current entry in the history stack.Dynamic Parameters: Navigate to routes with dynamic parameters.
The useNavigate
hook provides a flexible and powerful way to handle navigation in your React applications, making it easier to manage route changes based on user actions and application logic.
Protected Routes
Authentication Context
import React, { createContext, useContext, useState } from 'react';
// Create a context for authentication
const AuthContext = createContext();
export function AuthProvider({ children }) {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const login = () => setIsAuthenticated(true);
const logout = () => setIsAuthenticated(false);
return (
<AuthContext.Provider value={{ isAuthenticated, login, logout }}>
{children}
</AuthContext.Provider>
);
}
// Custom hook to use the Auth context
export const useAuth = () => useContext(AuthContext);
Protected Route Component
import React from 'react';
import { Navigate, Outlet } from 'react-router-dom';
import { useAuth } from './AuthProvider';
function ProtectedRoute() {
const { isAuthenticated } = useAuth();
return isAuthenticated ? <Outlet /> : <Navigate to="/login" />;
}
export default ProtectedRoute;
Defining Routes
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import { AuthProvider } from './AuthProvider';
import Home from './Home';
import Login from './Login';
import Dashboard from './Dashboard';
import ProtectedRoute from './ProtectedRoute';
function App() {
return (
<AuthProvider>
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/dashboard" element={<ProtectedRoute />}>
<Route path="" element={<Dashboard />} />
</Route>
</Routes>
</Router>
</AuthProvider>
);
}
export default App;
AuthProvider: Provides authentication state and functions (
login
,logout
) to manage it.useAuth Hook: Custom hook to access authentication state and functions.
ProtectedRoute Component: Checks authentication status and either renders the protected component (
<Outlet />
) or redirects to the login page using theNavigate
component.Routes Setup: Uses
ProtectedRoute
to protect the/dashboard
route.
Using the Navigate
component and custom authentication logic, you can effectively protect routes in a React application. This approach ensures that only authenticated users can access specific routes, enhancing the security and user experience of your application.
Subscribe to my newsletter
Read articles from Syed Aquib Ali directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Syed Aquib Ali
Syed Aquib Ali
I am a MERN stack developer who has learnt everything yet trying to polish his skills 🥂, I love backend more than frontend.