Everything so far has lived on one page. A real application usually needs multiple views — a home page, a profile page, a settings page — each at its own URL. React Router is the standard library for this: it matches the current URL to a component, without the browser doing a full page reload the way a plain <a href> normally would.
npm install react-router-domimport { BrowserRouter, Routes, Route } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/users/:id" element={<UserProfile />} />
</Routes>
</BrowserRouter>
);
}BrowserRouter wraps the whole app once, near the root; Routes looks at the current URL and renders whichever single Route's path matches.
A plain <a href="/about"> would trigger a full page reload — exactly what client-side routing exists to avoid. Link looks like an anchor tag but updates the URL and swaps the rendered route without one:
import { Link } from 'react-router-dom';
function Nav() {
return (
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
);
}:id in the route path from earlier becomes available inside the matched component via useParams:
import { useParams } from 'react-router-dom';
function UserProfile() {
const { id } = useParams(); // reads the :id segment from the current URL
const { data: user } = useFetch(`/api/users/${id}`); // the custom hook from earlier
return user ? <h1>{user.name}</h1> : <p>Loading...</p>;
}For redirecting after an action — a successful form submission, for instance — rather than in response to a click on a Link:
import { useNavigate } from 'react-router-dom';
function LoginForm() {
const navigate = useNavigate();
function handleSubmit(e) {
e.preventDefault();
navigate('/dashboard');
}
return <form onSubmit={handleSubmit}>{/* ... */}</form>;
}