Fix blank stations page by waiting for auth initialization
- Add useIsAuthInitialized hook to auth-gate for reactive auth state - Returns true once auth token is acquired and ready - Waits for waitForAuthInit() promise to resolve - Update useSavedStations hook to wait for auth before fetching - Add 'enabled: isAuthInitialized' to useQuery config - Prevents 401 errors from requests made before token is ready - Fixes race condition where hook fires before interceptor is set up The stations page was blank because useSavedStations() made an API call with refetchOnMount:true before the auth token interceptor was added, causing a 401 response that made the component unmount/remount, creating a React DOM error in the error boundary. Now the hook waits for isAuthInitialized to be true before making the initial API call, ensuring the token interceptor is ready. 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,8 @@
|
|||||||
* @ai-context Prevents race conditions between IndexedDB init and API calls
|
* @ai-context Prevents race conditions between IndexedDB init and API calls
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
// Global authentication readiness state
|
// Global authentication readiness state
|
||||||
let authInitialized = false;
|
let authInitialized = false;
|
||||||
let authInitPromise: Promise<void> | null = null;
|
let authInitPromise: Promise<void> | null = null;
|
||||||
@@ -99,4 +101,26 @@ const processRequestQueue = async () => {
|
|||||||
|
|
||||||
isProcessingQueue = false;
|
isProcessingQueue = false;
|
||||||
console.log('[Auth Gate] Finished processing queued requests');
|
console.log('[Auth Gate] Finished processing queued requests');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* React hook to track auth initialization state
|
||||||
|
* Returns true once auth is fully initialized with token
|
||||||
|
*/
|
||||||
|
export const useIsAuthInitialized = () => {
|
||||||
|
const [initialized, setInitialized] = useState(authInitialized);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (authInitialized) {
|
||||||
|
setInitialized(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for auth to initialize
|
||||||
|
waitForAuthInit().then(() => {
|
||||||
|
setInitialized(true);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return initialized;
|
||||||
};
|
};
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
|
import { useIsAuthInitialized } from '../../../core/auth/auth-gate';
|
||||||
import { stationsApi } from '../api/stations.api';
|
import { stationsApi } from '../api/stations.api';
|
||||||
import { SavedStation } from '../types/stations.types';
|
import { SavedStation } from '../types/stations.types';
|
||||||
|
|
||||||
@@ -33,12 +34,15 @@ interface UseSavedStationsOptions {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export function useSavedStations(options?: UseSavedStationsOptions) {
|
export function useSavedStations(options?: UseSavedStationsOptions) {
|
||||||
|
const isAuthInitialized = useIsAuthInitialized();
|
||||||
|
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: SAVED_STATIONS_QUERY_KEY,
|
queryKey: SAVED_STATIONS_QUERY_KEY,
|
||||||
queryFn: () => stationsApi.getSavedStations(),
|
queryFn: () => stationsApi.getSavedStations(),
|
||||||
staleTime: options?.staleTime ?? 5 * 60 * 1000, // 5 minutes default
|
staleTime: options?.staleTime ?? 5 * 60 * 1000, // 5 minutes default
|
||||||
refetchOnWindowFocus: options?.refetchOnWindowFocus ?? true,
|
refetchOnWindowFocus: options?.refetchOnWindowFocus ?? true,
|
||||||
refetchOnMount: true
|
refetchOnMount: true,
|
||||||
|
enabled: isAuthInitialized // Only fetch once auth is initialized
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user