React Router is a powerful library for managing navigation and routing in React applications. It enables developers to create single-page applications with dynamic routing, allowing users to navigate between different views without reloading the page. In this chapter, we'll cover everything from the basics to advanced concepts of React Router.
What is React Router?
React Router is a standard library for routing in React. It enables the navigation between views of various components in a React Application, allows changing the browser URL, and keeps the UI in sync with the URL.
Why Use React Router?
SPA Navigation: It provides seamless navigation for single-page applications (SPAs) without reloading the entire page.
Dynamic Routing: Routes can be dynamically added and removed.
URL Management: Simplifies the management of URLs and their corresponding components.
Nested Routes: Supports nested routing for complex applications.
Declarative: Routes are defined declaratively, making the code more readable and maintainable.
Basic Concepts of React Router
Let’s start with the basic concepts and setup of React Router in a React application.
Installation
To use React Router, you need to install the react-router-dom package:
npm install react-router-dom
Setting Up React Router
To set up React Router, you need to wrap your application in the BrowserRouter component and define some basic routes.
// App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';
const Home = () =>
Home
;
const About = () =>
About
;
const Contact = () =>
Contact
;
const App = () => {
return (
Home
About
Contact
);
};
export default App;
Explanation
BrowserRouter: Wraps the entire application and enables routing.
Link: Provides navigation to different routes without reloading the page.
Switch: Renders the first child <Route> that matches the location.
Route: Defines a route with a path and a component to render.
Output
When you run this application, you will see navigation links for “Home”, “About”, and “Contact”. Clicking these links will navigate to the corresponding components without reloading the page
Nested Routes
Nested routes allow you to define routes within other routes. This is useful for creating complex layouts with nested navigation.
Let’s create a blog application with nested routes for individual blog posts.
// App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link, useRouteMatch } from 'react-router-dom';
const Home = () =>
Home
;
const About = () =>
About
;
const Blog = () => {
let { path, url } = useRouteMatch();
return (
Blog
Post 1
Post 2
Please select a post.
);
};
const Post = ({ match }) => {
return
Requested Post ID: {match.params.postId}
;
};
const App = () => {
return (
Home
About
Blog
);
};
export default App;
Explanation
useRouteMatch: A hook that returns the match object for the current route. It provides the current path and url.
Nested Routes: Defined within the Blog component, allowing for navigation to individual blog posts.
Output
When you navigate to the “Blog” link, you will see links to “Post 1” and “Post 2”. Clicking these links will display the respective post ID.
URL Parameters and Query Strings
React Router allows you to extract URL parameters and query strings from the route.
URL Parameters
You can define URL parameters in the route path using a colon (:).
const User = ({ match }) => {
return
User ID: {match.params.userId}
;
};
const App = () => {
return (
Home
User 1
User 2
);
};
Explanation
match.params: Contains the parameters from the URL. In this case, userId is extracted from the URL.
Output
When you navigate to “/user/1” or “/user/2”, it will display “User ID: 1” or “User ID: 2”, respectively.
Query Strings
To handle query strings, you can use the useLocation hook from react-router-dom.
import { useLocation } from 'react-router-dom';
const useQuery = () => {
return new URLSearchParams(useLocation().search);
};
const Search = () => {
let query = useQuery();
return
Query: {query.get("q")}
;
};
const App = () => {
return (
Home
Search React
Search Router
);
};
Explanation
useLocation: Returns the location object representing the current URL.
URLSearchParams: Parses query strings from the URL.
Output
When you navigate to “/search?q=react” or “/search?q=router”, it will display “Query: react” or “Query: router”, respectively.
Redirects and Programmatic Navigation
React Router provides ways to redirect users and navigate programmatically.
Redirect Component
You can use the Redirect component to navigate to a different route.
import { Redirect } from 'react-router-dom';
const Home = () =>
Dynamic routes can be nested to handle more complex URL structures.
const Topic = ({ match }) => {
return
Requested Topic ID: {match.params.topicId}
;
};
const Topics = ({ match }) => {
return (
Topics
Components
Props v. State
Please select a topic.
);
};
const App = () => {
return (
);
};
Lazy Loading Routes
For performance optimization, routes can be lazy-loaded using React.lazy and Suspense.
import React, { Suspense, lazy } from 'react';
const Home = lazy(() => import('./Home'));
const About = lazy(() => import('./About'));
const App = () => {
return (
Loading...
}>
);
};
Explanation
React.lazy: Dynamically imports a component.
Suspense: Wraps components that should be rendered lazily and displays a fallback while loading.
Output
When you navigate to the respective routes, the components will be loaded dynamically, improving the initial load time.
Example 1: Blog Application with Nested Routes
In this example, we’ll build a blog application where users can view a list of blog posts and click on each post to view its details.
Step-by-Step Implementation
Step 1: Create the Blog and Post Components
First, create components for displaying the list of blog posts and individual post details.
// Post.js
import React from 'react';
import { useParams } from 'react-router-dom';
const Post = () => {
const { postId } = useParams();
return
Post ID: {postId}
;
};
export default Post;
// Blog.js
import React from 'react';
import { Link, Route, Switch, useRouteMatch } from 'react-router-dom';
import Post from './Post';
const Blog = () => {
let { path, url } = useRouteMatch();
return (
Blog
Post 1
Post 2
Post 3
Please select a post.
);
};
export default Blog;
Step 2: Create the Home Component
Create a simple Home component.
// Home.js
import React from 'react';
const Home = () => {
return
Home
;
};
export default Home;
Step 3: Set Up the App Component
Set up the App component to include routing for the home page and the blog.
// App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';
import Home from './Home';
import Blog from './Blog';
const App = () => {
return (
Home
Blog
);
};
export default App;
Explanation
useParams: Extracts the post ID from the URL.
useRouteMatch: Returns the match object, allowing us to construct nested routes.
Link: Navigates to different routes without reloading the page.
Route: Defines a route with a path and a component to render.
Switch: Renders the first matching route.
Output
When you run this application, you will see navigation links for “Home” and “Blog”. Clicking “Blog” will show links to individual blog posts. Clicking a post link will display its details.
Example 2: User Dashboard with Authentication
In this example, we’ll build a user dashboard where users must log in to access protected routes.
Step-by-Step Implementation
Step 1: Create the Login and Dashboard Components
First, create components for the login page and the dashboard.
// Login.js
import React from 'react';
import { useHistory } from 'react-router-dom';
const Login = () => {
let history = useHistory();
const handleLogin = () => {
// Simulate authentication
localStorage.setItem('auth', 'true');
history.push('/dashboard');
};
return (
Set up the App component to include routing for home, login, and the protected dashboard.
// App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';
import Home from './Home';
import Login from './Login';
import Dashboard from './Dashboard';
import PrivateRoute from './PrivateRoute';
const App = () => {
return (
Home
Login
Dashboard
);
};
export default App;
Explanation
useHistory: Provides access to the history instance, allowing navigation to different routes programmatically.
localStorage: Stores the authentication status.
PrivateRoute: A custom route component that checks if the user is authenticated. If not, it redirects to the login page.
Output
When you run this application, you will see navigation links for “Home”, “Login”, and “Dashboard”. Clicking “Dashboard” will redirect to the login page if not authenticated. After logging in, you will be redirected to the dashboard.
React Router is an essential library for managing navigation and routing in React applications. It allows you to create dynamic and nested routes, manage URL parameters and query strings, and implement redirects and route guards. By understanding and applying the concepts covered in this chapter, you can build complex, user-friendly navigation systems in your React applications. Happy coding !❤️