Core concepts of React Router v6 simplified
With the introduction of React Router v6, the way we handle routing in React applications has been significantly improved. This article provides a brief introduction to the core concepts of the new Router to get you started on implementing it on your projects.
Routes & Route
Routes: This is a component that serves as a container for individual Route
components. You can think of Routes
as a switch mechanism that renders the first Route
child that matches the current location.
Route: Represents an individual route in the application. It has two main props: path
and element
. The path
is the URL pattern to match against, and the element
is the React component that should be rendered for that path
.
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
In the example above, we set up routes that connect the <Home />
and <About />
Views. What is important to note here, is that this setup merely creates an association between the URL input of the browser and the visible components. It does not generate any tangible way of browsing the various paths within the application. For that, you need the <Link />
component
Nested Routes & Outlet
nested routes are established using the Routes
component inside another route. This allows you to define child routes inside a parent route, and the parent route can use the Outlet
component as a placeholder for where these child routes should render.
This concept may best be explained in a practical scenario. Imagine you’re building an admin dashboard with two primary sections: Users and Reports. The main dashboard page will have links to these sections, and clicking on them should change the content displayed while retaining the dashboard layout.
App.js
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Dashboard from './Dashboard';
import Users from './Users';
import Reports from './Reports';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/dashboard" element={<Dashboard />}>
<Route path="users" element={<Users />} />
<Route path="reports" element={<Reports />} />
</Route>
</Routes>
</BrowserRouter>
);
}
Dashboard.js
import { Outlet, Link } from 'react-router-dom';
function Dashboard() {
return (
<div>
<h1>Admin Dashboard</h1>
<nav>
<Link to="users">Users</Link> |
<Link to="reports">Reports</Link>
</nav>
<Outlet />
</div>
);
}
In this example,
- When you navigate to
/dashboard
, you'll see theDashboard
component with links toUsers
andReports
. - The
Outlet
component insideDashboard
acts as a placeholder for nested routes. - Navigating to
/dashboard/users
will display theUsers
component within theDashboard
layout. - Similarly, navigating to
/dashboard/reports
will show theReports
component within theDashboard
.
Worth noting, is that the JSX before Outlet
is present in both child routes. This makes creating dashboards mixing persistent and dynamic content very intuitive.
Link
The Link
component allows users to navigate between different routes. It generates an anchor (<a>
) tag underneath, but does so in a way that doesn't cause a full page reload, preserving the single-page application behavior.
<Link to="/about">About Us</Link>
In the example above, we have now created a clickable text element in our DOM. This can be placed anywhere in your web app and navigates the user to the <About />
View when they click on it.
This approach of directing traffic around a web app is preferred for static navigation, like nav menus, breadcrumbs, or inline links in text. When rendered, they generate anchor tags that are SEO-friendly in the sense that they let web crawlers navigate and index the app with ease.
useNavigate
useNavigate
is a hook that returns a function that when called, navigates to a specified route. It is a programmatic alternative to the more static alternative, Link
.
import { useNavigate } from 'react-router-dom';
function LoginForm() {
const navigate = useNavigate();
const handleLogin = async (credentials) => {
const user = await loginUser(credentials);
if (user.role === 'admin') {
navigate('/admin/dashboard');
} else {
navigate(`/user/${user.id}`);
}
}
return (
// Your form JSX...
);
}
The example above shows how we can use this hook to conditionally navigate to different routes based on the users role. If they are an admin, they are sent to one page, while if they are a regular user, they are sent to another. All without needing any additional input from the user.
Additionally, this hook is a great way of implementing a “go back” button.
function BackButton() {
const navigate = useNavigate();
return (
<button onClick={() => navigate(-1)}>Go Back</button>
);
}
It lets users navigate back in the history stack using a negative number as the argument. This is specially great in terms of UX, as it takes the user back to wherever they came from. Even if they came from an entirely different website, when they click on this button, they will go back to the previous site.
Another scenario where useNavigate
shines is protected routes. you may for instance want to redirect the user somewhere else if a condition is not met when they access a route.
Conclusion
The new version of React Router has overhauled and simplified how routing works for directing traffic across the components. In this article we looked at the various main concepts of the new React router, with the aim of learning the essentials needed to get started implementing the technology in any web app.