Published: February 22 2023

React Router v6 - Listen to location (route) change without history.listen

This is a quick post on how to detect route changes with React Router v6 to execute code on location change in a React app.

I recently updated a React project from React Router v5 to v6 and ran into an issue with listening to route changes. The previous version of React Router (v5) allowed you to access the browser history object which included the history.listen() method to subscribe to location changes.

The new React Router v6 does not provide access to history but instead recommends using a useEffect() hook function with the dependency array set to [location]. The useEffect() hook will execute any time a dependency changes so in this case whenever the location changes. The location can be accessed with the useLocation() from React Router v6.

Execute on route change with React Router 6

This snippet shows how to listen to location change with React Router v6 by passing the location object in the dependency array to a useEffect() hook function.

The callback function simply increments a location change counter and a logs the current pathname to the console.

const location = useLocation();
const [count, setCount] = useState(0);

useEffect(() => {
    // execute on location change
    setCount(count + 1);
    console.log('Location changed!', location.pathname);
}, [location]);


React component that listens to location change

This is the complete React component that the above snippet is taken from, it includes a nav bar and a couple of routes to test the location change listener.

You can see the code running and tinker with it yourself on StackBlitz at https://stackblitz.com/edit/react-router-v6-location-change-history-listen

NOTE: With [location] as the dependency the code will execute even if you navigate to the same page (e.g. if you click the Home link from the home page). If you only want to execute when changing to a different route use [location.pathname] instead.

import React, { useEffect, useState } from 'react';
import { Routes, Route, Navigate, NavLink, useLocation } from 'react-router-dom';

import { Home } from './home';
import { About } from './about';

export { App };

function App() {
    const location = useLocation();
    const [count, setCount] = useState(0);

    useEffect(() => {
        // execute on location change
        setCount(count + 1);
        console.log('Location changed!', location.pathname);
    }, [location]);

    return (
        <div>
            <nav className="navbar navbar-expand navbar-dark bg-dark px-3">
                <div className="navbar-nav">
                    <NavLink to="/" className="nav-item nav-link">Home</NavLink>
                    <NavLink to="/about" className="nav-item nav-link">About</NavLink>
                </div>
            </nav>
            <div className="container pt-4 pb-4">
                <Routes>
                    <Route path="/" element={<Home />} />
                    <Route path="/about" element={<About />} />
                    <Route path="*" element={<Navigate to="/" />} />
                </Routes>
                <hr />
                <ul>
                    <li>Route change count: {count}</li>
                    <li>Current route: {location.pathname}</li>
                </ul>
            </div>
        </div>
    );
}

 


Need Some React Help?

Search fiverr for freelance React developers.


Follow me for updates

On Twitter or RSS.


When I'm not coding...

Me and Tina are on a motorcycle adventure around Australia.
Come along for the ride!


Comments


Supported by