These libraries manage navigation in React apps without full page reloads. react-router-dom is the standard for web, react-router is its core logic, @reach/router is deprecated, and wouter is a lightweight alternative.
These libraries handle navigation in React applications without requiring full page reloads. While they share the same goal, their maintenance status, API design, and intended use cases differ significantly. Let's compare how they tackle common routing problems.
@reach/router is no longer maintained.
// @reach/router: Deprecated API
import { Router, Link } from "@reach/router";
// Do not use in new projects
react-router is the core logic package.
react-router-dom instead.// react-router: Core exports
import { Routes, Route } from "react-router";
// Typically re-exported via react-router-dom for web
react-router-dom is the standard for web.
react-router features plus browser specifics.// react-router-dom: Web-specific entry
import { BrowserRouter, Routes } from "react-router-dom";
// Use this for standard web applications
wouter is actively maintained.
// wouter: Lightweight alternative
import { Router, Route } from "wouter";
// Use for small bundles or Preact projects
react-router-dom uses a component-based structure.
BrowserRouter.Routes and Route components.// react-router-dom: Component-based routes
<BrowserRouter>
<Routes>
<Route path="/about" element={<About />} />
</Routes>
</BrowserRouter>
react-router follows the same pattern.
react-router-dom re-exports these, the API is identical.// react-router: Same component API
<Router history={customHistory}>
<Routes>
<Route path="/about" element={<About />} />
</Routes>
</Router>
@reach/router used a similar component style.
Router and Route but with different props.// @reach/router: Legacy component style
<Router>
<About path="/about" />
</Router>
wouter supports both components and hooks.
Route components or the useRoute hook.// wouter: Hook-based or component
<Router>
<Route path="/about" component={About} />
</Router>
// Or using hooks inside a component
const [match, params] = useRoute("/users/:id");
react-router-dom provides a <Link> component.
to prop for paths.// react-router-dom: Link component
<Link to="/about">About Us</Link>
react-router exposes navigation hooks.
useNavigate allows programmatic control.// react-router: Programmatic navigation
const navigate = useNavigate();
<button onClick={() => navigate("/about")} />;
@reach/router had its own <Link>.
// @reach/router: Legacy Link
<Link to="/about">About Us</Link>
wouter offers a minimal <Link>.
useLocation hook for manual control.// wouter: Minimal Link
<Link href="/about">About Us</Link>
// Or hook
const [location, setLocation] = useLocation();
react-router-dom uses colon syntax.
useParams hook.// react-router-dom: Params
<Route path="/user/:id" element={<User />} />
// Inside component
const { id } = useParams();
react-router handles matching logic.
// react-router: Core matching
// Logic is shared with react-router-dom
const { id } = useParams();
@reach/router used similar syntax.
// @reach/router: Props based
function User({ userId }) { ... }
<Route path="/user/:userId" component={User} />
wouter uses standard capture groups.
useRoute.// wouter: Hook params
const [match, { id }] = useRoute("/user/:id");
While the differences are clear, these libraries also share many core ideas and tools. Here are key overlaps:
// All: Functional Component
function Page() { return <div>Hello</div>; }
// All: Intercepting clicks
// Implementation varies, goal is the same
// All: History sync
// window.history is manipulated internally
| Feature | react-router-dom | wouter | @reach/router |
|---|---|---|---|
| Status | β Active | β Active | β Deprecated |
| Size | π¦ Standard | πͺΆ Tiny | π¦ Legacy |
| API Style | Components + Hooks | Hooks + Components | Components (Legacy) |
| Use Case | Enterprise Apps | Small Tools | Do Not Use |
react-router-dom is the safe bet for most teams. It has the features, the docs, and the community support.
wouter is the specialist choice. If you count every kilobyte or use Preact, this is your tool.
@reach/router and react-router (core) have specific roles. Avoid Reach entirely. Use core react-router only if you aren't building for the web.
Final Thought: Routing is infrastructure. Pick the tool that will still be supported when you need to fix a bug two years from now.
Avoid this package for any new development. It is officially deprecated and has been merged into React Router v6. Continuing to use it creates technical debt and potential security risks. You should migrate existing projects to react-router-dom immediately.
Select this package only if you are building for a non-DOM environment like React Native. For standard web applications, this package is a dependency of react-router-dom and does not need to be installed separately. Using it directly on the web requires manual history configuration. Stick to the DOM-specific package for browser projects.
Choose this library for most professional web applications requiring robust routing features. It offers a complete ecosystem with nested routes, protected paths, and extensive documentation. The learning curve is reasonable, and community support is vast. It is the industry standard for scaling React applications.
Opt for this solution when bundle size is a critical constraint or when using Preact. It provides a hooks-first API that feels very natural in modern React code. The feature set is smaller, so ensure it meets your specific needs before committing. It excels in side projects or lightweight micro-frontends.
Next Generation Routing for React
You can also find the docs in the website directory.
MIT License Copyright (c) 2018-present, Ryan Florence