import { type ReactNode, Suspense, useState, useLayoutEffect } from 'react' import { Navigate, useLocation } from 'react-router-dom' import { useAuth } from '../contexts/AuthContext' import { PageLoader } from './PageLoader' // Mounts only once Suspense has resolved (chunk is ready). // useLayoutEffect fires before the browser paints, so setState here causes a // synchronous re-render — content becomes visible in the same paint with no // intermediate loader flash for cached chunks. function ContentReady({ onReady }: { onReady: () => void }) { useLayoutEffect(() => { onReady() // eslint-disable-next-line react-hooks/exhaustive-deps }, []) return null } type Props = { children: ReactNode } export function ProtectedRoute({ children }: Props) { const { user, loading } = useAuth() const location = useLocation() // Always start false so the loader covers any intermediate render state. // For cached chunks, ContentReady's useLayoutEffect fires before the first // paint and flips this synchronously — no visible flash. const [contentReady, setContentReady] = useState(false) if (!loading && !user) { return } const showLoader = loading || !contentReady return ( <> {showLoader && } {!loading && user && (
setContentReady(true)} /> {children}
)} ) }