React - Routing (Hash)
Overview
Estimated time: 20–30 minutes
Learn a minimal approach to routing without libraries by using the URL hash to pick which view to render.
Learning Objectives
- Understand the role of a router in SPAs.
- Implement a tiny hash-based router.
Try it: Tiny Hash Router
View source
const { useState, useEffect } = React;
function useHash(){
const [hash, setHash] = useState(() => window.location.hash || '#/' );
useEffect(() => {
const onHash = () => setHash(window.location.hash || '#/');
window.addEventListener('hashchange', onHash);
return () => window.removeEventListener('hashchange', onHash);
}, []);
return hash;
}
function App(){
const hash = useHash();
let page = hash.replace('#','');
if (page === '/') page = '/home';
return (
<div>
<nav>
<a href="#/home">Home</a> | <a href="#/about">About</a>
</nav>
{page === '/home' && <h3>Home</h3>}
{page === '/about' && <h3>About</h3>}
</div>
);
}
ReactDOM.createRoot(document.getElementById('try-router')).render(<App />);
Syntax primer
window.location.hash
stores a fragment like#/home
that doesn’t trigger a page reload.hashchange
event fires when the hash changes.
Common pitfalls
- This is a minimal router: no params, nested routes, or guards. Use a routing library for production.
Checks for Understanding
- What’s the difference between hash-based routing and history API routing?
- Why doesn’t changing the hash cause a full page reload?
Show answers
- Hash-based uses the URL fragment (
#...
) and doesn’t touch the server path; history API manipulates the real path and requires server support. - The fragment is not sent to the server; browsers update it client-side and fire
hashchange
events only.
Exercises
- Add a third page (
/settings
) and a nav link; verify it responds to back/forward. - Implement simple route params (e.g.,
#/user/42
) and display the user id. - Persist the last visited route in
localStorage
and restore it on load.