Using React Router for Navigation: Best Practices and Examples

Using React Router for Navigation: Best Practices and Examples

Get the most out of React Router
Sky Hernandez β€’ 2023 July 03 β€’ Read time 14 min read
Learn how you can get the most out of React Router using the following examples as best practices.
  • twitter
  • facebook
React

The React Router library is widely used for navigation purposes in single-page applications. This tool empowers developers to generate dynamic routes, manage nested routes, and send URL parameters. This article aims to explore optimal techniques for utilizing React Router, provide instances of its application, and highlight prevalent errors to avoid.


Setting Up React Router

To utilize React Router in your project, you need to incorporate it first. Simply enter this command into your terminal to accomplish this:

Copied to clipboard!
npm install react-router-dom

After installation, you can generate routes by importing essential components from React Router, such as BrowserRouter and Route. You can create a basic route with the following code:

Copied to clipboard! Playground
import { BrowserRouter, Route, Routes } from 'react-router-dom'

function App() {
    return (
        <BrowserRouter>
            <Routes>
                <Route path="/" element={<Home />} />
            </Routes>
        </BrowserRouter>
    )
}
Basic route using React Router

This code sets up a route for the homepage of your application. When a user navigates to the root URL of your application, the Home component will be rendered.

You can also add multiple Route components inside a Routes component, like so:

Copied to clipboard! Playground
import { BrowserRouter, Route, Routes } from 'react-router-dom'

function App() {
    return (
        <BrowserRouter>
            <Routes>
                <Route path="/" element={<Home />} />
                <Route path="/about" element={<About/>} />
                <Route path="/contact" element={<Contact/>} />
            </Routes>
        </BrowserRouter>
    )
}
How to create multiple routes

This code creates routes for the homepage, about page, and contact page of your application. When a user navigates to any of these URLs, the corresponding component will be rendered.


Best Practices for React Router

There are some rules you should follow to get the most out of React Router. First, you should keep your routes clean and simple. Don't use inline functions for route components:

Copied to clipboard!
// ❌ Instead of this
<Route path="/about" element={() => <AboutPage />} />

Using inline functions for route components can lead to errors as the element prop expects a React.ReactNode to be passed. Always define your components separately and pass them as props to the Route component:

Copied to clipboard! Playground
// βœ”οΈ Do this
const AboutPage = () => {
    // Component logic here
}

<Route path="/about" element={<AboutPage />} />

By defining the component separately, you ensure that it works as intended, and the correct component is rendered.

Maintaining simple and comprehensible routes is essential. It is recommended to assign descriptive and memorable names to your routes that accurately represent the content that can be found at the corresponding URL.

Using dynamic routing with parameters

React Router enables the passing of URL parameters to components, providing a means of generating dynamic content. As an example, if you have a blog, you can create a route that accepts a blog post ID as a parameter.

Copied to clipboard!
<Route path="/blog/:postId" element={<BlogPost />} />

This code creates a route that accepts a postId parameter. When a user navigates to /blog/123, the BlogPost component will be rendered with the postId set to 123. To access the postId inside of the component, you can use the useParams hook.

Using named routes for easier maintenance

Using named routes can enhance the maintainability of your application as it enables you to refer to routes by their designated names instead of their corresponding URLs.

This can be particularly beneficial when there is a need to modify your URLs. To establish a named route, use the path prop, which you can later reference in other parts of your code:

Copied to clipboard!
<Route path="/about" element={<About />} />

// You can later create a link to the about page using the named route
<Link to="/about">About</Link>
Use descriptive paths
Looking to improve your skills? Check out our interactive course to master React from start to finish.
Master Reactinfo Remove ads

Examples of React Router in Action

  • Creating a multi-page website with React Router: React Router is a practical option for developing a multi-page website that features multiple routes. You can generate routes for various web pages such as a homepage, about page, contact page, and services page. Each of these routes can display a distinct component with its unique content.
  • Implementing a client-side search feature with React Router: You can use React Router to manage search results if your website has a search bar. A user's search query might trigger the creation of a new route where the query string is included as a parameter in the URL. This allows users to easily share or save the search results for later use.
  • Using React Router with Redux for state management: Redux and React Router work well together for managing your app's data. Depending on the current state of your Redux store, you can design routes that render various parts of your application. For instance, you can implement a protected route that only displays for logged-in users.
  • Creating a protected route with authentication using React Router: Using React Router's redirect function, you can create a secure route that requires authentication. For example, a route can display a login page if the user is not logged in, and a protected component otherwise. If a user tries to access the protected component without authenticating, they will be redirected to the login page.

Common Mistakes to Avoid

To avoid common mistakes when using React Router, keep the following points in mind:

Don’t overcomplicate routes

Copied to clipboard! Playground
// ❌ Don't overcomplicate routes
const App = () => {
    return (
        <BrowserRouter>
            <Routes>
                <Route path="/" element={<Home />} />
                <Route path="/users" element={<UserList />} />
                <Route path="/users/:userId" element={<UserProfile />} />
                <Route path="/users/:userId/posts" element={<UserPosts />} />
                <Route path="/users/:userId/posts/:postId" element={<UserPostDetails />} />
                <Route path="/users/:userId/settings" element={<UserSettings />} />
                <Route path="/admin" element={<AdminDashboard />} />
                <Route path="/admin/users" element={<AdminUserList />} />
                <Route path="/admin/users/:userId" element={<AdminUserProfile />} />
                {/* ...many more routes */}
            </Routes>
        </BrowserRouter>
    )
}

It's easy to overcomplicate your routes by creating too many nested routes or passing too many URL parameters. Keep your routes simple and easy to understand.

Copied to clipboard! Playground
// βœ”οΈ Do use simplified routes
const App = () => {
    return (
        <BrowserRouter>
            <Routes>
                <Route path="/" element={<Home />} />
                <Route path="/users" element={<UserRoutes />} />
                <Route path="/admin" element={<AdminRoutes />} />
                {/* ...other top-level routes */}
            </Routes>
        </BrowserRouter>
    )
}

Not handling 404 errors properly

Copied to clipboard! Playground
// ❌ Improper handling of 404 errors
const App = () => {
    return (
        <BrowserRouter>
            <Routes>
                <Route path="/" element={<Home />} />
                <Route path="/about" element={<About />} />
                <Route path="/contact" element={<Contact />} />
                {/* ...other routes, without catching 404 */}
            </Routes>
        </BrowserRouter>
    )
}

Create a route to catch any URLs that don't correspond to your specified paths so that you can properly handle 404 errors. If your users accidentally visit an incorrect URL, they won't be met with a blank page.

Copied to clipboard! Playground
// βœ”οΈ Handling 404 errors properly
const App = () => {
    return (
        <BrowserRouter>
            <Routes>
                <Route path="/" element={<Home />} />
                <Route path="/about" element={<About />} />
                <Route path="/contact" element={<Contact />} />
                {/* ...other routes */}
                <Route path=”*” element={<NotFound />} />
            </Routes>
        </BrowserRouter>
    )
}

// NotFound component for 404 errors
const NotFound = () => {
    return (
        <div>
            <h2>404 Not Found</h2>
            <p>Sorry, the page you are looking for does not exist.</p>
        </div>
    )
}

Not using React Router's built-in features effectively

Copied to clipboard! Playground
// ❌ Not using React Router's built-in features effectively
import { BrowserRouter, Route } from 'react-router-dom'

const App = () => {
    return (
        <BrowserRouter>
            <nav>
                <ul>
                    <li><a href="/">Home</a></li>
                    <li><a href="/about">About</a></li>
                    <li><a href="/contact">Contact</a></li>
                </ul>
            </nav>

            <Route path="/" component={<Home />} />
            <Route path="/about" component={<About />} />
            <Route path="/contact" component={<Contact />} />
        </BrowserRouter>
    )
}

The Link and NavLink components are only two of the numerous built-in functionalities of React Router. Use them wisely to create more readable and easily maintainable code and a better user experience.

Copied to clipboard! Playground
// βœ”οΈ Using React Router's built-in features effectively
import { BrowserRouter, Route, NavLink } from 'react-router-dom'

const App = () => {
    return (
        <BrowserRouter>
            <nav>
                <ul>
                    <li><NavLink to="/">Home</NavLink></li>
                    <li><NavLink to="/about">About</NavLink></li>
                    <li><NavLink to="/contact">Contact</NavLink></li>
               </ul>
            </nav>

            <Route exact path="/" component={<Home />} />
            <Route path="/about" component={<About />} />
            <Route path="/contact" component={<Contact />} />
        </BrowserRouter>
    )
}

Bonus: React Hooks and Code Splitting with React Router

The efficiency and maintainability of your web application can be enhanced by combining React Hooks and code splitting with React Router. In this bonus section, we will take a quick look at how to use both of them.

useNavigate Hook

As mentioned earlier, React Router version 6 introduced the useNavigate hook, which is helpful for programmatic navigation within your React project. The useNavigate hook provides an imperative method that can be used to change the current location. For example:

Copied to clipboard! Playground
import { useNavigate } from 'react-router-dom'

const Home = () => {
    const navigate = useNavigate()

    const handleClick = () => {
        navigate('/about')
    }

    return (
        <div>
            <h1>Home</h1>
            <button onClick={handleClick}>Go to About</button>
        </div>
    )
}
Navigating programmatically in React Router

Code Splitting

Code splitting is a technique used to improve the efficiency of your web application by splitting your code into smaller parts that are loaded on demand.

This can be particularly beneficial for larger applications with numerous components and routes. React Router has built-in support for code splitting with the React.lazy function. For example:

Copied to clipboard! Playground
import { lazy, Suspense } from 'react'
import { BrowserRouter, Route, Routes } from 'react-router-dom'

const Home = lazy(() => import('./Home'))
const About = lazy(() => import('./About'))
const Contact = lazy(() => import('./Contact'))

function App() {
    return (
        <BrowserRouter>
            <Suspense fallback={<div>Loading...</div>}>
                <Routes>
                    <Route path="/" element={<Home />} />
                    <Route path="/about" element={<About />} />
                    <Route path="/contact" element={<Contact />} />
                </Routes>
            </Suspense>
        </BrowserRouter>
    )
}
Lazy loading React components

The code implements the React.lazy function to dynamically import the Home, About, and Contact components only when they are needed. The Suspense component is used to display a loading spinner while the component is being loaded.


Conclusion

React Router is an essential tool for navigation in single-page applications. By following best practices and using examples of React Router in action, you can create effective and efficient routes for your web application.

Keep in mind that clean, scalable code is the result of avoiding common pitfalls and making appropriate use of React Router's native features. By leveraging the capabilities of React Hooks and code separation, you can further enhance the efficiency and reliability of your application.

  • twitter
  • facebook
React
Did you find this page helpful?
πŸ“š More Webtips
Frontend Course Dashboard
Master the Art of Frontend
  • check Access 100+ interactive lessons
  • check Unlimited access to hundreds of tutorials
  • check Prepare for technical interviews
Become a Pro

Courses

Recommended

This site uses cookies We use cookies to understand visitors and create a better experience for you. By clicking on "Accept", you accept its use. To find out more, please see our privacy policy.