We use nested routing in our React application so that a parent component has control over its child component at the route level.
In this tutorial we will learn how to use Nested Routes with React Router.
In order to get you started, create a new React project. Afterward, install React Router and read the following tutorial to get yourself aligned to what follows next.
What Are Nested Routes?
Nested routes in React Router are a way of defining routes in a hierarchical manner. In this arrangement, a route( parent route ) can have child routes. Each child route represents a portion of the URL.
For example, on a user page one gets presented multiple tabs (e.g. Profile, Account) to navigate through a user’s information.
By clicking these tabs, the URL in the browser will change, but instead of replacing the whole page, only the content of the tab gets replaced.
In the following we will recreate this scenario with React Router.
Setting Up The Project
To be able to follow along, add these lines of code to the file:
App.css
nav a { text-decoration: none; font-weight: bold; color: #000; padding-left: 10px; }
Home.jsx
import React from 'react'; const Home = () => { return <div>This is Home Page.</div>; }; export default Home;
User.jsx
import React from 'react' const User = () => { return ( <div>This is User Page.</div> ) } export default User
Profile.jsx
import React from 'react' const Profile = () => { return ( <div>You are now in Profile page.</div> ) } export default Profile
Account.jsx
import React from 'react'; const Account = () => { return <div>You are now in Account page.</div>; }; export default Account;
PageNotFound.jsx
import React from 'react' const PageNotFound = () => { return ( <div>PageNotFound</div> ) } export default PageNotFound
App.jsx
import './App.css'; function App() { return ( <> <h1>React Router</h1> </> ); } export default App;
main.jsx
In the main.jsx file, enter the following:
import React from 'react'; import ReactDOM from 'react-dom/client'; import { BrowserRouter } from 'react-router-dom'; import App from './App.jsx'; import './index.css'; ReactDOM.createRoot(document.getElementById('root')).render( <React.StrictMode> <BrowserRouter> <App /> </BrowserRouter> </React.StrictMode> );
This should hold everything in our app where routing is needed. That means, if we need routing in our entire app, we must wrap our higher component with BrowserRouter
.
Defining Routes
To illustrate how this works and how you can implement nested routes step by step in React yourself, we will start off with the following example:
import './App.css'; import { Routes, Route, Link } from 'react-router-dom'; import Home from './Home'; import User from './User'; import PageNotFound from './PageNotFound'; function App() { return ( <> <h1>React Router</h1> <nav> <Link to="/home">Home</Link> <Link to="/user">User</Link> </nav> <Routes> <Route index element={<Home />} /> <Route path="home" element={<Home />} /> <Route path="user" element={<User />} /> <Route path="*" element={<PageNotFound />} /> </Routes> </> ); } export default App;
In this function component we have matching Link
and Route
components from React Router for the /home and /user routes.
Furthermore, we have a so-called Index Route loaded with the Home component and a so-called No Match Route loaded with the PageNotFound component.
Also Read: A Complete Beginner’s Guide to React Router
Both act as fallback routes. From here, we will explore the concept of Nested Route.
Nested Routes in React Router
We will continue working on the User component, because this is the place where we want to have the nested routing via tabs.
Therefore, we will create a new set of Link
components (which will be our un-styled tabs) which navigate a user to their profile and their account.
User.jsx
import { Link } from 'react-router-dom'; const User = () => { return ( <> <h1>User</h1> <p>This is User Page.</p> <nav> <Link to="/user/profile">Profile</Link> <Link to="/user/account">Account</Link> </nav> </> ); }; export default User;
We are using absolute paths here to navigate a user from their profile to their account and vice versa, however, we could also use relative paths as a best practice.
Because the User component sits in the /user route, the Link
components can anticipate their parent route (here: /user) and just append relative paths (here: profile and account) to it (e.g. /user/profile):
User.jsx
import { Link } from 'react-router-dom'; const User = () => { return ( <> <h1>User</h1> <p>This is User Page.</p> <nav> <Link to="profile">Profile</Link> <Link to="account">Account</Link> </nav> </> ); }; export default User;
At this time, when we attempt to click one of these links in our React application, we would get stranded at our No Match Route i.e PageNotFound.
This tells us that we didn’t map these routes (here: /user/profile and /user/account) to any actual Route
components yet.
Therefore, we will add these two new routes as so-called Nested Routes to our /user route:
App.jsx
import './App.css'; import { Routes, Route, Link } from 'react-router-dom'; import Home from './Home'; import User from './User'; import PageNotFound from './PageNotFound'; import Profile from './Profile'; import Account from './Account'; function App() { return ( <> <h1>React Router</h1> <nav> <Link to="/home">Home</Link> <Link to="/user">User</Link> </nav> <Routes> <Route index element={<Home />} /> <Route path="home" element={<Home />} /> <Route path="user" element={<User />}> <Route path="profile" element={<Profile />} /> <Route path="account" element={<Account />} /> </Route> <Route path="*" element={<PageNotFound />} /> </Routes> </> ); } export default App;
The Route
components map to the Link
components in a one to one relationship now. However, there can be more than one Link
component linking to the same route, so it’s actually a one to many relationship.
When testing this in the browser, we will see that only the User components shows up and not its nested Profile component nor its nested Account component when clicking their respective links.
We are missing the crucial Outlet
component from React Router:
User.jsx
import { Link, Outlet } from 'react-router-dom'; const User = () => { return ( <> <h1>User</h1> <p>This is User Page.</p> <nav> <Link to="profile">Profile</Link> <Link to="account">Account</Link> </nav> <Outlet /> </> ); }; export default User;
The Outlet
component renders the matching child route with its respective component (here either Profile or Account component) from the parent Routes’ component collection of Route
components.
If there is no /profile and no /account route matching (e.g. /user/settings), you will see only the User component showing up.
To avoid this, you can add a combination of Index and No Match Routes. Afterward, the default route will be the /profile route:
App.jsx
import './App.css'; import { Routes, Route, Link } from 'react-router-dom'; import Home from './Home'; import User from './User'; import PageNotFound from './PageNotFound'; import Profile from './Profile'; import Account from './Account'; function App() { return ( <> <h1>React Router</h1> <nav> <Link to="/home">Home</Link> <Link to="/user">User</Link> </nav> <Routes> <Route index element={<Home />} /> <Route path="home" element={<Home />} /> <Route path="user" element={<User />}> <Route index element={<Profile />} /> <Route path="profile" element={<Profile />} /> <Route path="account" element={<Account />} /> <Route path="*" element={<PageNotFound />} /> </Route> <Route path="*" element={<PageNotFound />} /> </Routes> </> ); } export default App;
That’s it. While the User component always renders the tabs as navigation, its content (Outlet) gets replaced by the matching nested route (either Profile or Account component based on /user/profile or /user/account route).
If none of these routes are matched when visiting the /user route, the application will show either the Profile component (if route matches exactly /user) or the PageNotFound component (if route does not match, e.g. /user/setting) showing up.
Conclusion
We hope this post has helped you set up a basic nested route. This feature improves code organization and maintainability while enhancing user experience.
Nested routes are a valuable addition to React Router and should be considered when building complex applications.
Similar articles you may like
- Using Vite to create a new React app
- React Components – A Theoretical View
- Exploring MUI Theming Options: Customization Made Easy
- useState in React: A Complete Guide
Add comment