React itself has no built-in router. React Router is the most widely used library for adding client-side navigation to a single-page app.
npm install react-router-dom
Basic setup
import { createBrowserRouter, RouterProvider, Link, Outlet } from 'react-router-dom';
function Layout() {
return (
<div>
<nav>
<Link to="/">Home</Link>
<Link to="/students">Students</Link>
</nav>
<Outlet /> {/* matched child route renders here */}
</div>
);
}
const router = createBrowserRouter([
{
path: '/',
element: <Layout />,
children: [
{ index: true, element: <Home /> },
{ path: 'students', element: <StudentList /> },
{ path: 'students/:id', element: <StudentDetail /> },
{ path: '*', element: <NotFound /> },
],
},
]);
function App() {
return <RouterProvider router={router} />;
}
Reading URL parameters and navigating programmatically
import { useParams, useNavigate, useSearchParams } from 'react-router-dom';
function StudentDetail() {
const { id } = useParams(); // /students/:id
const [searchParams] = useSearchParams(); // ?tab=grades
const navigate = useNavigate();
return (
<div>
<p>Student ID: {id}, tab: {searchParams.get('tab')}</p>
<button onClick={() => navigate('/students')}>Back to list</button>
</div>
);
}
Data loading tied to a route (v6.4+ / v7)
{
path: 'students/:id',
element: <StudentDetail />,
loader: async ({ params }) => {
const res = await fetch(`/api/students/${params.id}`);
return res.json();
},
}
function StudentDetail() {
const student = useLoaderData(); // data is ready before the component renders
return <h2>{student.name}</h2>;
}
Note on Next.js / Remix routing
If you use a meta-framework like Next.js (App Router) or Remix, routing is file-based instead — a file's path in the app/ or routes/ folder determines its URL, and React Router usually isn't needed at all.