React Router’s is not just cleaner—it solves flicker issues, avoids security glitches, and keeps your code sane. Here's the lowdown👇
const navigate = useNavigate();
const isAuthenticated = useSelector(...);
useEffect(() => {
if (!isAuthenticated) navigate('/login');
}, [isAuthenticated, navigate]);
But this approach has big flaws:
- The protected component still briefly renders before the redirect runs.
- A console log or side effect may fire, even if the user isn’t authorized.
- This isn’t just a UX glitch—it can leak data or trigger sensitive logic before redirecting.
âś… Why is Way Better
Here's how your route should look:
import { Navigate } from 'react-router-dom';
const ProtectedPage = () => {
const isAuthenticated = useSelector(...);
if (!isAuthenticated) {
return <Navigate to={"/login"} />;
}
return <SecretStuff />;
};
Why it's superior:
- Declarative: You tell React exactly what to render.
- No flicker: Unauthorized users never see protected UI even for a split second.
- Cleaner code: No more juggling useEffect, useNavigate, or loading flags.
- React‑idiomatic: Leverages JSX for what it’s good at—conditionals.
đź§© Bonus Tips
Want to preserve the current URL after login? Use .
Combine this with a reusable private route wrapper to apply protection across multiple routes.
âś… TL;DR
- Bad: useEffect + useNavigate = flash of protected UI + potential data leaks.
- Good: = clean, safe, flicker-free routing.
Top comments (0)