How to Update useLocation Hook in React

In React Router, the useLocation hook provides access to the current URL’s location object, but it is a read-only representation of the router’s current state. This article explains why you cannot modify the useLocation object directly and demonstrates the correct method to update it by triggering a route transition using the useNavigate hook, including how to pass and read state during navigation.

Understanding useLocation

The useLocation hook returns a location object that contains details about the current URL, such as the pathname, search (query parameters), hash, and custom state. Because this hook represents the current state of the address bar, mutating its properties directly (e.g., trying to write location.pathname = '/new-route') will not work and will not trigger a component re-render. To update the location, you must initiate a navigation event.

Updating Location via useNavigate

In React Router v6, the standard way to update the current location is by using the useNavigate hook. Calling the navigation function updates the browser’s history stack, which causes React Router to update the useLocation hook automatically in any active components.

Here is a practical example of how to update the location programmatically:

import React from 'react';
import { useNavigate, useLocation } from 'react-router-dom';

function NavigationComponent() {
  const navigate = useNavigate();
  const location = useLocation();

  const handleNavigation = () => {
    // This updates the URL and triggers an update to the useLocation hook
    navigate('/dashboard', { state: { user: 'JohnDoe' } });
  };

  return (
    <div>
      <p>Current Path: {location.pathname}</p>
      <button onClick={handleNavigation}>Go to Dashboard</button>
    </div>
  );
}

Passing and Accessing State

A common reason to update the location is to pass temporary, non-URL-visible data between pages. You can achieve this by passing a state object as the second argument to the navigate function.

Once the navigation is complete, the destination component can access this state using the useLocation hook:

import React from 'react';
import { useLocation } from 'react-router-dom';

function Dashboard() {
  const location = useLocation();
  
  // Access the passed state safely
  const username = location.state?.user || 'Guest';

  return (
    <div>
      <h1>Dashboard</h1>
      <p>Welcome back, {username}!</p>
    </div>
  );
}

By utilizing useNavigate to change the route, you ensure that the useLocation hook remains synchronized with the browser history and the actual URL of your application.