From f1dd48808be27a5d9d23349f7f637d2f07e22007 Mon Sep 17 00:00:00 2001 From: Eric Gullickson <16152721+ericgullickson@users.noreply.github.com> Date: Tue, 4 Nov 2025 19:26:21 -0600 Subject: [PATCH] Fix blank stations page - add auth gate guard in App.tsx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ROOT CAUSE: Race condition where StationsPage renders before auth token is ready, causing DOM state mismatch. Timeline of the bug: 1. Auth0 sets isAuthenticated=true 2. App renders StationsPage before isAuthInitialized=true 3. useSavedStations hook is disabled (enabled: false) 4. Google Maps loads and manipulates DOM 5. Auth token finally acquired, isAuthInitialized=true 6. Component re-renders with query now enabled 7. React tries to remove DOM nodes already removed by Google Maps 8. NotFoundError: removeChild fails SOLUTION: Add isAuthGateReady check in App.tsx before rendering protected routes. Show "Initializing session..." until auth gate is fully initialized. Changes: - Import useIsAuthInitialized hook in App.tsx - Call hook in App component - Add guard check after isAuthenticated check - Show loading UI if authenticated but auth gate not ready - Add debug logs to track render flow Now the page won't render until BOTH: 1. isAuthenticated=true (Auth0) 2. isAuthInitialized=true (our token gate) This prevents the race condition that causes the removeChild DOM error. 🤖 Generated with Claude Code Co-Authored-By: Claude --- frontend/src/App.tsx | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index eb71082..b72eb23 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -6,6 +6,7 @@ import React, { useState, useEffect, useTransition, useCallback, lazy } from 're import { useQueryClient } from '@tanstack/react-query'; import { Routes, Route, Navigate } from 'react-router-dom'; import { useAuth0 } from '@auth0/auth0-react'; +import { useIsAuthInitialized } from './core/auth/auth-gate'; import { motion, AnimatePresence } from 'framer-motion'; import { ThemeProvider } from '@mui/material/styles'; import CssBaseline from '@mui/material/CssBaseline'; @@ -237,7 +238,9 @@ const AddVehicleScreen: React.FC = ({ onBack, onAdded }) function App() { const { isLoading, isAuthenticated, user } = useAuth0(); + const isAuthGateReady = useIsAuthInitialized(); const [_isPending, startTransition] = useTransition(); + console.log('[DEBUG App] Render check - isLoading:', isLoading, 'isAuthenticated:', isAuthenticated, 'isAuthGateReady:', isAuthGateReady); // Initialize data synchronization const { prefetchForNavigation } = useDataSync(); @@ -380,6 +383,32 @@ function App() { ); } + // Wait for auth gate to be ready before rendering protected routes + // This prevents a race condition where the page renders before the auth token is ready + if (!isAuthGateReady) { + console.log('[DEBUG App] Auth gate not ready yet, showing loading state'); + if (mobileMode) { + return ( + + + +
+
Initializing session...
+
+
+
+ ); + } + return ( + + +
+
Initializing session...
+
+
+ ); + } + // Mobile app rendering if (mobileMode) { return (