What is it?
React Router (now react-router v7) is the routing library most
non-Next React apps use. It handles URL → component mapping, nested
layouts, route loaders, and client-side navigation without page
reloads. If you're using Vite + React without Next.js, you're using
React Router.
Why it matters
Routing decisions shape app architecture. Knowing how loaders, actions, and lazy routes work in React Router transfers directly to Next.js, TanStack Router, and Remix — they all borrowed the same patterns.
What to learn
- Browser history vs hash routing
- Defining routes: file-based vs object-based
- Nested routes and
<Outlet />for shared layouts - Route params and search params: typed access
- Loaders and actions (data fetching + mutations at the route level)
- Lazy-loaded routes with
lazy()for code splitting - Programmatic navigation:
useNavigate, redirects from loaders
Common pitfall
Fetching data inside useEffect in a route component. React Router
loaders run before the route renders, so the page paints with data
already in hand. Effects make the user see a flash of empty state every
navigation. Loaders are the right place.
Resources
Primary (free):
- React Router docs · docs
- React Router 7 — Migration guide · docs
- Remix's loader/action pattern · docs
Practice
Build a small two-route app: a list page (/users) and a detail page
(/users/:id). Use a loader to fetch on the server / before navigation.
Add a search-params filter on the list page. Done when navigating between
routes never shows a loading spinner before content paints.
Outcomes
- Configure routes with nested layouts and shared
<Outlet />s. - Fetch data in a loader instead of
useEffect. - Read and update search params with React Router's typed APIs.
- Code-split a route to keep the home page fast.