React Router started in 2014 back when React itself was still figuring things out. The idea is simple: different URLs show different components. No more manually parsing window.location
like some kind of caveman. The original announcement shows how experimental this all was back then.
The Three Things You Need to Understand
Three main pieces: Routers (the outer wrapper), Routes (URL matching), and Links (navigation that doesn't suck). That's it. Everything else is just optimization and edge cases.
BrowserRouter uses clean URLs (/about
) but needs server configuration. HashRouter uses ugly URLs (/#/about
) but works anywhere. MemoryRouter exists for testing and server stuff. Pick BrowserRouter unless you have a good reason not to, like when you're deploying to GitHub Pages.
The Remix Merger Confusion
They merged with Remix in 2023, which confused the hell out of everyone. Suddenly React Router could do server-side rendering, which was weird because it was always a client-side thing.
The deal is this: v7 gives you server-side rendering if you want it ("framework mode"), but you can totally ignore it and keep doing client-side routing like before. Most React apps are SPAs anyway, so this doesn't affect you unless you specifically need SEO or initial page load performance. The React Router v7 announcement explains the vision behind the merger.
Version Upgrade Reality
The v5 to v6 migration was a pain in the ass because they completely changed the API. No more Switch
, now it's Routes
. No more <Route component={}>
, now it's <Route element={}>
. Nested routing got completely redesigned. The migration codemod helped but couldn't handle all edge cases.
The good news: v6 to v7 is supposed to be non-breaking. I've upgraded three apps so far and haven't hit any show-stoppers, which is honestly surprising.
TypeScript Support That Actually Works
v7 has auto-generated types, which is nice when it works. Route params get typed automatically, loader data gets typed, all that good stuff. But TypeScript with React Router has always been a bit of a dance - sometimes the types are wrong and you end up with as any
in weird places. The type generation setup requires some boilerplate but pays off in larger apps.
The error messages are still cryptic as hell, but at least now you get compile-time errors for broken routes.
Production Reality Check
I've used React Router in everything from side projects to apps with millions of users. It works, it's stable, and when something breaks it's usually your code, not React Router. The bundle size analysis shows ~45KB, it plays nice with code splitting, and it doesn't do anything too magical that you can't debug. Companies like Airbnb and Netflix have used it at massive scale.
The main gotcha is nested routing, which looks simple in the docs but will make you question your life choices when you're trying to implement auth guards or complex layouts. Once you get it though, it's powerful.
Performance in the real world: Router transitions are fast - we're talking single-digit milliseconds for route matching. The bottleneck is always your components re-rendering or data fetching, not the router itself. I've seen apps with 100+ routes that still route instantly.
Memory usage stays reasonable even with deep nesting. React Router doesn't keep all components in memory - it properly unmounts routes when you navigate away. The biggest memory leak I've seen was developers keeping state in parent components that never unmounted.