Reactadvanced 9 min
Show different screens for different URLs in a single-page app, with a tiny router and then React Router.
What routing means in a single-page app, how to build a tiny router from state, and what the same idea looks like with React Router.
Real apps have several screens: home, about, profile. Users expect the URL to change, the back button to work, and links to be shareable. Routing connects the address to what is shown.
A single-page application (SPA) loads once and then swaps the content with JavaScript, instead of loading a new HTML page for each link.
The core idea of a router: keep the "current path" in state, and render a different component depending on it. Links change the path without a full page reload.
In real projects you use the React Router library, which also updates the browser address bar and handles the back button, nested routes and URL parameters. Install it with npm install react-router-dom. Its code looks like this:
useParams() reads :id from the URL, similar to req.params in Express.
A tiny router you can run here. It keeps the path in state and shows the matching page, including a route with a parameter:
path is state, starting at /.go, which stops the browser's normal navigation with preventDefault and updates the state instead. The page does not reload./users/42, path.split("/")[2] pulls out 42, which is passed to User as a prop. This is what useParams does for you in React Router.Click each link in the preview and watch the content change. Then add a /contact page.
<a href> tags in a SPA, which cause full page reloads. Use <Link> from the router.useParams.index.html for every path, so refreshing a deep link gives a 404.<Link> and useParams in real apps.Next: sharing data across components with context.
const [path, setPath] = useState("/");
{path === "/" && <Home />}
{path === "/about" && <About />}import { BrowserRouter, Routes, Route, Link, useParams } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Home</Link> <Link to="/about">About</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/users/:id" element={<User />} />
</Routes>
</BrowserRouter>
);
}function Home() {
return <h2>Home</h2>;
}
function About() {
return <h2>About us</h2>;
}
function User({ id }) {
return <h2>User profile #{id}</h2>;
}
function App() {
const [path, setPath] = useState("/");
function go(e, to) {
e.preventDefault();
setPath(to);
}
let page;
if (path === "/") page = <Home />;
else if (path === "/about") page = <About />;
else if (path.startsWith("/users/")) page = <User id={path.split("/")[2]} />;
else page = <h2>404: page not found</h2>;
const link = (to, label) => (
<a
href={to}
onClick={(e) => go(e, to)}
style={{ marginRight: 12, fontWeight: path === to ? "bold" : "normal" }}
>
{label}
</a>
);
return (
<div style={{ fontFamily: "system-ui" }}>
<nav>
{link("/", "Home")}
{link("/about", "About")}
{link("/users/42", "User 42")}
{link("/nowhere", "Broken link")}
</nav>
<p>Current path: {path}</p>
{page}
</div>
);
}