React is a popular JavaScript library that provides several features for creating dynamic single-page applications. And one of the most important features of React is React Router, which enables you to handle navigation within your app.
In this blog, we will be sharing ten expert tips and tricks that help you master React routing and optimize your app navigation for a seamless user experience.
Before diving into advanced concepts, it is essential to understand the basic components of React Router. The two most important components are-
If you are building a complex application with multiple sections, it is a good idea to use nested routes. Nested routes allow you to organize your app into smaller sections and handle navigation more efficiently.
Additionally, it allows better component encapsulation, improves code splitting, gives granular control over routing, and makes code scalable.
React Router provides several hooks that allow you to handle navigation and state within your components. The most commonly used hooks are useHistory, useParams, and useLocation. These hooks are essential for building dynamic and responsive user interfaces.
Lazy loading is a technique that allows you to load components only when they are needed, which can improve the performance of your app. React Router provides a built-in method for lazy loading called React.lazy. You can use this method to load components asynchronously, which can speed up the initial load time of your app.
Here, we are using React.lazy function to create lazy-loaded components for our HomePage, AboutPage, and ContactPage. Each component is loaded asynchronously only when it's needed.
1 import React, { lazy, Suspense } from 'react'; 2 import { Route, Switch } from 'react-router-dom'; 3 4 const HomePage = lazy(() => import('./pages/HomePage')); 5 const AboutPage = lazy(() => import('./pages/AboutPage')); 6 const ContactPage = lazy(() => import('./pages/ContactPage')); 7 8 function App() { 9 return ( 10 <div> 11 <Suspense fallback={<div>Loading...</div>}> 12 <Switch> 13 <Route exact path="/" component={HomePage} /> 14 <Route exact path="/about" component={AboutPage} /> 15 <Route exact path="/contact" component={ContactPage} /> 16 </Switch> 17 </Suspense> 18 </div> 19 ); 20 } 21
The “Suspense” component is to specify a fallback UI to display while the lazy-loaded components are being loaded. In this case, we're simply displaying the text "Loading...".
Finally, we're using the “Route” and “Switch” components from react-router-dom to define our routes and specify which component to render for each route. The “exact” prop is used to ensure that the component is only rendered for an exact match of the route path.
Error handling is an important aspect of any application. When it comes to React routing, it is essential to handle errors related to routing. For example, if a user enters an incorrect URL, you should handle that error and redirect them to the appropriate page.
Route guards are functions that are executed before rendering a Route component. They are useful for checking if a user is authorized to access a particular route or if certain conditions are met.
1 // Define your guard function 2 3 function isAuthenticated(route, params) { 4 // Check if user is authenticated 5 const isAuthenticated = /* your authentication logic here */; 6 7 if (!isAuthenticated) { 8 // Redirect to login page or unauthorized page 9 window.location.href = '/login'; 10 return false; 11 } 12 13 return true; 14 } 15
Once you define your Route guard apply your guard function to Route.
1 // Apply guard function to Route 2 3 window.onhashchange = function() { 4 const route = window.location.hash.substring(1); 5 const params = /* any necessary parameters */; 6 7 // Apply your guard function to the route 8 9 const isAllowed = isAuthenticated(route, params); 10 if (!isAllowed) { 11 // Cancel navigation 12 window.history.back(); 13 } 14 }; 15
Dynamic route matching is a technique that allows you to match URLs with different parameters. For example, if you have a blog with multiple posts, you can use dynamic route matching to match each post with its own URL. React Router provides a built-in method for dynamic route matching called “path-to-regexp”.
1 const pathToRegexp = require('path-to-regexp'); 2 3 // Define the route pattern with a parameter placeholder 4 const pattern = '/users/:id'; 5 6 // Convert the route pattern to a regular expression 7 const regex = pathToRegexp(pattern); 8 9 // Test a URL to see if it matches the route pattern 10 const url = '/users/123'; 11 const match = regex.exec(url); 12 13 if (match) { 14 // Extract the parameter value from the URL using the parameter key 15 const key = 'id'; 16 const value = match[1]; // The first match group corresponds to the parameter value 17 18 console.log(`Matched route "${pattern}" with param "${key}": ${value}`); 19 } 20 else 21 { 22 console.log(`No match for route "${pattern}"`); 23 } 24
Query parameters are a way to pass data between pages using the URL. They are useful for filtering data or passing user input to the next page. React Router provides a built-in method for query parameters called “useLocation”.
The following steps demonstrate how to pass data in React.js using query parameters with the useLocation hook:
1 import { useLocation } from 'react-router-dom';
1 import { useLocation } from 'react-router-dom'; 2 3 function UserDetails() { 4 const location = useLocation(); 5 const searchParams = new URLSearchParams(location.search); 6 const userId = searchParams.get('id'); 7 8 // Fetch the user data using the userId 9 // ... 10 11 return ( 12 <div> 13 <h1>User Details</h1> 14 <p>User ID: {userId}</p> 15 {/* Display the user details */} 16 </div> 17 ); 18 } 19
URL generation is a technique that allows you to generate URLs dynamically. This is useful for creating links to different parts of your app or sharing URLs with other users. React Router provides a built-in method for URL generation called “Link”.
In the example discussed in the use query parameter section, we need to use the “userId” to fetch the user data from an API or a local data source. Finally, we can render the user details in the component.
And to pass the “id” parameter from the list of users component to the user details component, we can use the “Link” component from react-router-dom with the “to” prop that includes the query parameter:
1 import { Link } from 'react-router-dom'; 2 3 function UserList() { 4 const users = [ /* array of user objects */ ]; 5 6 return ( 7 <div> 8 <h1>User List</h1> 9 <ul> 10 {users.map(user => ( 11 <li key={user.id}> 12 <Link to={`/user-details?id=${user.id}`}>{user.name}</Link> 13 </li> 14 ))} 15 </ul> 16 </div> 17 ); 18 } 19
In this example, we use the “Link” component to create a link to the user details page (/user-details) with the “id” query parameter set to the ID of the current user (user.id). When the user clicks on the link, they will be taken to the user details page and the “useLocation” hook will extract the “id” parameter from the URL.
Layout component is a wrapper component that can be used to add common elements to multiple pages. For example, if you have a header and footer that appear on every page, you can use a layout component to wrap each page and add the header and footer. This can make your code more modular and easier to maintain.
Here's how we can create the layout component:
1 import React from 'react'; 2 const Layout = ({ children }) => { 3 return ( 4 <div> 5 <header> 6 <h1>My Website</h1> 7 </header> 8 <main>{children}</main> 9 <footer> 10 <p>© 2023 My Website</p> 11 </footer> 12 </div> 13 ); 14 }; 15 16 export default Layout; 17 18
Here, we have a functional component named “Layout” that takes in a “children” prop. The “children” prop is a special prop in React that allows us to pass in other components that will be rendered inside our “Layout” component.
In this component, we have a <header>
section that contains the website title, a <main>
section where our other components will be rendered, and a <footer>
section that contains the copyright notice.
Now, let's say we have a “HomePage” component that we want to render inside our “Layout” component. Here's how we can do it:
1 import React from 'react'; 2 import Layout from './Layout'; 3 4 const HomePage = () => { 5 return ( 6 <div> 7 <h2>Welcome to my website!</h2> 8 <p>Here's some content for the home page...</p> 9 </div> 10 ); 11 }; 12 13 const App = () => { 14 return ( 15 <Layout> 16 <HomePage /> 17 </Layout> 18 ); 19 }; 20 21 export default App; 22
Here, we import our “Layout” component and create a “HomePage” component that contains some content for the home page. Then, we wrap our “HomePage” component inside our “Layout” component by passing it as a child to the “Layout” component.
When we run our “App” component, we'll see that the “HomePage” component is rendered inside our “Layout” component, with the header and footer sections appearing on every page of our website.
Mastering React routing is essential for building successful single-page web applications. By following these ten expert tips and tricks, you can optimize your app navigation and provide a seamless user experience.
Understanding the basic components of React Router, using nested routes, implementing React Router hooks, lazy loading, error handling, route guards, dynamic route matching, query parameters, URL generation, and layout components are all essential for building a successful app.
So, follow these expert tips and master React routing like a pro.
Besides that, if you are looking for the best app development platform that can speed up your React web app development try DhiWise React Builder and build a web app in just a few steps without affecting the code quality.
Sign up now to explore more about DhiWise and its features.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.