From e4a09a676e8d0e860bdd349cc8661b13423f679a Mon Sep 17 00:00:00 2001 From: dwindown Date: Sun, 4 Jan 2026 18:05:38 +0700 Subject: [PATCH] Fix navigation issues with ProtectedRoute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed infinite redirect loop and navigation blocking in ProtectedRoute component. The issue was that the useEffect was running on every render when navigating between admin routes. ## Changes: - Added hasChecked state to ensure effect only runs once per mount - Prevents multiple redirects and navigation blocking - Allows smooth navigation between admin and member pages after login ## Technical Details: - Before: useEffect ran on every render with requireAdmin in dependencies - After: useEffect runs once when auth loading completes - This prevents React Router navigation conflicts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- src/components/ProtectedRoute.tsx | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/ProtectedRoute.tsx b/src/components/ProtectedRoute.tsx index 5cfbd29..922f1aa 100644 --- a/src/components/ProtectedRoute.tsx +++ b/src/components/ProtectedRoute.tsx @@ -1,4 +1,4 @@ -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { useAuth } from '@/hooks/useAuth'; import { Skeleton } from '@/components/ui/skeleton'; @@ -11,9 +11,13 @@ interface ProtectedRouteProps { export function ProtectedRoute({ children, requireAdmin = false }: ProtectedRouteProps) { const { user, loading: authLoading } = useAuth(); const navigate = useNavigate(); + const [hasChecked, setHasChecked] = useState(false); useEffect(() => { - if (!authLoading) { + // Only run effect once after auth loading completes + if (!authLoading && !hasChecked) { + setHasChecked(true); + if (!user) { // Save current URL to redirect back after login const currentPath = window.location.pathname + window.location.search; @@ -32,10 +36,10 @@ export function ProtectedRoute({ children, requireAdmin = false }: ProtectedRout } } } - }, [user, authLoading, navigate, requireAdmin]); + }, [user, authLoading, navigate, requireAdmin, hasChecked]); // Show loading skeleton while checking auth - if (authLoading) { + if (authLoading || !hasChecked) { return (