multica/apps/web/features/auth/initializer.tsx
Bohan Jiang 461dad0dd5
perf(web): parallelize auth init and non-blocking dashboard layout (#220)
- Fire getMe() and listWorkspaces() in parallel instead of serially,
  saving one network round-trip (~200ms on cloud)
- Render dashboard sidebar shell immediately once user is authenticated,
  show loading indicator in content area while workspace hydrates

Closes MUL-41
2026-03-31 15:22:58 +08:00

46 lines
1.4 KiB
TypeScript

"use client";
import { useEffect, type ReactNode } from "react";
import { useAuthStore } from "./store";
import { useWorkspaceStore } from "@/features/workspace";
import { api } from "@/shared/api";
import { createLogger } from "@/shared/logger";
const logger = createLogger("auth");
/**
* Initializes auth + workspace state from localStorage on mount.
* Fires getMe() and listWorkspaces() in parallel when a cached token exists.
*/
export function AuthInitializer({ children }: { children: ReactNode }) {
useEffect(() => {
const token = localStorage.getItem("multica_token");
if (!token) {
useAuthStore.setState({ isLoading: false });
return;
}
api.setToken(token);
const wsId = localStorage.getItem("multica_workspace_id");
// Fire getMe and listWorkspaces in parallel
const mePromise = api.getMe();
const wsPromise = api.listWorkspaces();
Promise.all([mePromise, wsPromise])
.then(([user, wsList]) => {
useAuthStore.setState({ user, isLoading: false });
useWorkspaceStore.getState().hydrateWorkspace(wsList, wsId);
})
.catch((err) => {
logger.error("auth init failed", err);
api.setToken(null);
api.setWorkspaceId(null);
localStorage.removeItem("multica_token");
localStorage.removeItem("multica_workspace_id");
useAuthStore.setState({ user: null, isLoading: false });
});
}, []);
return <>{children}</>;
}