The One Missing Line That Breaks React Router Login Redirects
Broken post-login redirects are a top user-complaint generator in any app with authentication. The fix is two lines of code, but skipping them means every authenticated user starts their session annoyed and disoriented.
A route guard that redirects to `/login` without carrying the original path loses the user's intent. The fix is passing `location.pathname` through React Router's `state` prop on `<Navigate>`, then reading it back with `useLocation` on the login page to redirect post-login. Two `replace` calls keep the browser history clean so the back button doesn't dump users back onto the login form.
A subtle trap is using the global `window.location` instead of the hook `useLocation()`. It works by accident when the guard mounts on the protected route, but breaks under reuse or when components persist across navigations. The consistent pattern is `useLocation` everywhere.
The whole mechanism hinges on a single handoff: `state.from` carries the intended destination across the redirect, and the login page's `navigate(from, { replace: true })` completes the round trip.
The bug isn't a routing mistake; it's a missing handoff. The guard knows where the user wanted to go but throws that information away before the login page can act on it.
Using `window.location` instead of `useLocation()` works by coincidence on first mount but is a time bomb: any refactor that keeps the guard mounted across route changes will read the wrong path.
The `replace: true` on both ends of the redirect is what makes the flow feel seamless. Without it, the browser history traps users in a login loop when they press back.