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.
2. Check for Incorrect Link Navigation
A frequent mistake is manually adding the hash symbol inside
<Link> components. React Router’s
HashRouter automatically appends the hash to your
paths.
Incorrect:
<Link to="#/profile">Profile</Link>Correct:
<Link to="/profile">Profile</Link>
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:
- Open your browser’s DevTools and select the Components tab.
- Search for
HashRouterorRouter. - Look at the hooks or props section in the right panel.
- Locate the routing context to see the active routes and match
objects. If the
matchprop isnullfor 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.
- In v5: Route matching is exact by default only if
specified, and you use the
<Switch>component. - In v6: Routes match exactly by default,
<Switch>is replaced by<Routes>, and theelementprop is used instead ofcomponent.
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>
);
}