Skip to content

[FE-03] Fix race condition in Zustand auth hydration causing flash of protected content #271

Description

@Leothosine

Problem

frontend/providers/ProtectedRoute.tsx:19 uses a hardcoded 100ms setTimeout to wait for Zustand's persist middleware to rehydrate from localStorage. On slower devices the auth check at line 24 executes before hydration completes. The result is that unauthenticated users briefly see protected admin content before being redirected.

Proposed Solution

  1. In the auth Zustand store, add a _hasHydrated: boolean field (default: false)
  2. Use Zustand's onRehydrateStorage callback to set _hasHydrated = true once persistence finishes
  3. Create a useAuthRehydrated() hook that subscribes to _hasHydrated
  4. Update ProtectedRoute to render a full-screen skeleton loader until _hasHydrated is true, then perform the auth check
  5. Remove the setTimeout entirely

Acceptance Criteria

  • No protected content is visible before the auth check completes on any device speed
  • A full-screen skeleton (not null) renders during hydration
  • _hasHydrated resolves correctly on cold start, page refresh, and back-navigation
  • Verified with Chrome DevTools CPU throttling set to 6x slowdown
  • No setTimeout or arbitrary delay remains in auth initialization code

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions