How to Debug HashRouter in React

Debugging HashRouter in React involves identifying why your application is failing to sync the UI with the URL hash (#/). This article covers the most common causes of HashRouter failures—such as incorrect link formatting, routing mismatches, and configuration errors—and provides actionable steps, code snippets, and browser tools to help you quickly diagnose and resolve these routing issues.

1. Verify the URL Structure and Hash Presence

The most common issue with HashRouter is an incorrect URL format. HashRouter relies on the hash symbol (#) to manage routing without sending requests to the server.

Open your browser’s address bar and verify that the URL contains the hash. For example: * Correct: http://localhost:3000/#/dashboard * Incorrect: http://localhost:3000/dashboard

If the hash is missing, your server may try to handle the route, resulting in a 404 error. Ensure your application is wrapped in <HashRouter> at the root level, typically in index.js or main.jsx.

A frequent mistake is manually adding the hash symbol inside <Link> components. React Router’s HashRouter automatically appends the hash to your paths.

If you manually include the # in the to prop, React Router will generate a path like /#/#/profile, which will fail to match your route definitions.

3. Monitor Route Changes in the Console

You can track whether the browser is successfully registering hash changes by adding a global event listener in your browser console. Run the following snippet in the DevTools console:

window.addEventListener('hashchange', () => console.log('Current Hash:', window.location.hash));

Navigate through your app. If the console does not log the new hash values, your navigation elements are either preventing default behavior or are not correctly updating the window’s location.

4. Log the Location Object inside React

To see what React Router is actually perceiving, log the location object using the useLocation hook. Create a temporary debugging component and place it inside your <HashRouter>:

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

function DebugRouter() {
  const location = useLocation();
  console.log('React Router Location:', location);
  return null;
}

Add <DebugRouter /> right inside your <HashRouter> component. It will print the current pathname, search, and hash state to your console every time the route changes, allowing you to see if the path matches your <Route> paths.

5. Use React Developer Tools to Inspect Route Matches

Install the React Developer Tools browser extension to inspect the component tree:

  1. Open your browser’s DevTools and select the Components tab.
  2. Search for HashRouter or Router.
  3. Look at the hooks or props section in the right panel.
  4. Locate the routing context to see the active routes and match objects. If the match prop is null for your component, your route path definition does not match the URL path.

6. Look for React Router Version Discrepancies

Routing behavior differs significantly between React Router v5 and v6.

Ensure your syntax matches your installed version. For React Router v6, a basic structure should look like this:

import { HashRouter, Routes, Route } from 'react-router-dom';

function App() {
  return (
    <HashRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </HashRouter>
  );
}