In this lesson, we’ll learn how to create routes and navigation links in a React application using the React Router library. React Router provides a set of components that allow us to define the routes of our application and navigate between them.
Creating a Router
The first step in using React Router is to create a router. The router is responsible for handling the routing of our application and rendering the appropriate components for each route.
To create a router, we’ll need to import the BrowserRouter
component from react-router-dom
and wrap our application with it.
import { BrowserRouter } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<div>
{/* Our routes and components go here */}
</div>
</BrowserRouter>
);
}
Defining Routes
Once we have a router set up, we can define our routes using the Route
component. The Route
component takes a path
prop that specifies the URL path that the route should match, and a component
prop that specifies the component that should be rendered for the route.
For example, to create a route for the /home
path that renders a Home
component, we can use the following code:
import { BrowserRouter, Route } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<div>
<Route path="/home" component={Home} />
</div>
</BrowserRouter>
);
}
function Home() {
return <h1>Home</h1>;
}
Creating Navigation Links
Once we have our routes defined, we can create navigation links between them using the Link
component. The Link
component takes a to
prop that specifies the path that the link should navigate to, and renders a clickable element that will navigate to the specified route when clicked.
For example, to create a link to the /home
route, we can use the following code:
import { BrowserRouter, Route, Link } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<div>
<Route path="/home" component={Home} />
<Link to="/home">Home</Link>
</div>
</BrowserRouter>
);
}
function Home() {
return <h1>Home</h1>;
}
Dynamic Routes
We can also create dynamic routes that include parameters in the URL path. For example, to create a route for /users/:id
that renders a User
component, we can use the following code:
import { BrowserRouter, Route, Link, useParams } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<div>
<Route path="/users/:id" component={User} />
<Link to="/users/123">User 123</Link>
</div>
</BrowserRouter>
);
}
function User() {
const { id } = useParams();
return <h1>User {id}</h1>;
}
In this example, we’ve created a route for /users/:id
that renders the User
component. We’ve also created a navigation link that points to /users/123
. When the link is clicked, the User
component will be rendered with the id
parameter set to 123
.
We can access the dynamic parameters using the useParams
hook. The useParams
hook returns an object with the dynamic parameters as properties. In this example, we’ve destructured the id
parameter from the useParams
hook and used it in the User
component.
Nested Routes
We can also create nested routes by rendering a Route
component inside another component. For example, we can create a User
component that includes routes for the /users/:id
and /users/:id/posts
paths like this:
import { BrowserRouter, Route, Link, useParams } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<div>
<Route path="/users/:id" component={User} />
<Link to="/users/123">User 123</Link>
<Link to="/users/123/posts">User 123 Posts</Link>
</div>
</BrowserRouter>
);
}
function User() {
return (
<div>
<Route path="/users/:id" component={UserProfile} />
<Route path="/users/:id/posts" component={UserPosts} />
</div>
);
}
function UserProfile() {
const { id } = useParams();
return <h1>User {id} Profile</h1>;
}
function UserPosts() {
const { id } = useParams();
return <h1>User {id} Posts</h1>;
}
In this example, we’ve created two routes inside the User
component: one for /users/:id
that renders the UserProfile
component, and one for /users/:id/posts
that renders the UserPosts
component. We’ve also created two navigation links that point to these routes.
When the User
component is rendered, both routes will be checked and the appropriate component will be rendered based on the current URL path.
Switching Between Routes
Sometimes we want to create routes that have overlapping paths, where one route is a subset of another. For example, we might want to create a route for /users/:id
that renders the UserProfile
component and a route for /users/:id/posts
that renders the UserPosts
component, but we also want to render the UserProfile
component when the /users/:id/posts/:postId
path is accessed.
To do this, we can use the Switch
component from react-router-dom
. The Switch
component allows us to specify a list of routes, and it will only render the first route that matches the current URL path.
We can use the Switch
component like this:
import { BrowserRouter, Route, Link, Switch, useParams } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<div>
<Switch>
<Route path="/users/:id/posts/:postId" component={UserPost} />
<Route path="/users/:id/posts" component={UserPosts} />
<Route path="/users/:id" component={UserProfile} />
</Switch>
<Link to="/users/123">User 123</Link>
<Link to="/users/123/posts">User 123 Posts</Link>
<Link to="/users/123/posts/456">User 123 Post 456</Link>
</div>
</BrowserRouter>
);
}
function UserProfile() {
const { id } = useParams();
return <h1>User {id} Profile</h1>;
}
function UserPosts() {
const { id } = useParams();
return <h1>User {id} Posts</h1>;
}
function UserPost() {
const { id, postId } = useParams();
return <h1>User {id} Post {postId}</h1>;
}
In this example, we’ve created three routes inside a Switch
component: one for /users/:id/posts/:postId
that renders the UserPost
component, one for /users/:id/posts
that renders the UserPosts
component, and one for /users/:id
that renders the UserProfile
component.
When the Switch
component is rendered, it will only render the first route that matches the current URL path. In this example, when the /users/:id/posts/:postId
path is accessed, the UserPost
component will be rendered. When the /users/:id/posts
path is accessed, the UserPosts
component will be rendered. And when the /users/:id
path is accessed, the UserProfile
component will be rendered.
This allows us to create routes that have overlapping paths and still ensure that only the appropriate component is rendered for each path.
Redirecting Routes
Sometimes we want to redirect users to a different route if they access a certain path. For example, we might want to redirect users from the /old-path
to the /new-path
if they try to access the /old-path
.
To do this, we can use the Redirect
component from react-router-dom
. The Redirect
component allows us to specify a from
path and a to
path, and it will redirect users from the from
path to the to
path when it is rendered.
We can use the Redirect
component like this:
import { BrowserRouter, Route, Link, Redirect } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<div>
<Route exact path="/old-path" render={() => <Redirect to="/new-path" />} />
<Link to="/old-path">Old Path</Link>
<Link to="/new-path">New Path</Link>
</div>
</BrowserRouter>
);
}
In this example, we’ve created a route for the /old-path
that renders the Redirect
component. The Redirect
component is set to redirect users from the /old-path
to the /new-path
when it is rendered.
When a user clicks the “Old Path” link, they will be redirected to the /new-path
.
The Redirect
component can also be used inside a Switch
component to redirect users to a different route if they access a certain path.
Conclusion
In this article, we learned how to use React Router to create routes and navigation links for our React applications. We learned how to create dynamic routes and how to use the Switch
and Redirect
components to control which routes are rendered and redirect users to different routes.
Exercises
To review these concepts, we will go through a series of exercises designed to test your understanding and apply what you have learned.
Create a route for the path /users/:id
that renders the UserProfile
component.
<Route path="/users/:id" component={UserProfile} />
Create a route for the path /users/:id/posts
that renders the UserPosts
component.
<Route path="/users/:id/posts" component={UserPosts} />
Create a route for the path /users/:id/posts/:postId
that renders the UserPost
component.
<Route path="/users/:id/posts/:postId" component={UserPost} />
Create a Switch
component that contains the three routes you created in the previous exercises.
<Switch>
<Route path="/users/:id/posts/:postId" component={UserPost} />
<Route path="/users/:id/posts" component={UserPosts} />
<Route path="/users/:id" component={UserProfile} />
</Switch>
Create a Link
component for each of the three routes you created in the previous exercises.
<Link to="/users/:id">User Profile</Link>
<Link to="/users/:id/posts">User Posts</Link>
<Link to="/users/:id/posts/:postId">User Post</Link>