Files
suaveplan/apps/demo/src/client/lib/session-context.tsx
2026-05-27 23:29:53 +01:00

54 lines
1.4 KiB
TypeScript

/**
* Session context — polls `/api/auth/get-session` on mount and exposes
* `useSession()` and a `refresh()` to forms.
*/
import React, {
createContext,
useCallback,
useContext,
useEffect,
useMemo,
useState,
} from "react";
import { fetchSession, type Session } from "./auth-client.js";
export interface SessionContextValue {
readonly session: Session | null;
readonly loading: boolean;
readonly refresh: () => Promise<void>;
}
const SessionContext = createContext<SessionContextValue | null>(null);
export function useSession(): SessionContextValue {
const ctx = useContext(SessionContext);
if (ctx === null) throw new Error("useSession must be inside <SessionProvider>");
return ctx;
}
export function SessionProvider({ children }: { children: React.ReactNode }): React.JSX.Element {
const [session, setSession] = useState<Session | null>(null);
const [loading, setLoading] = useState(true);
const refresh = useCallback(async () => {
setLoading(true);
try {
const next = await fetchSession();
setSession(next);
} finally {
setLoading(false);
}
}, []);
useEffect(() => {
void refresh();
}, [refresh]);
const value = useMemo<SessionContextValue>(
() => ({ session, loading, refresh }),
[session, loading, refresh]
);
return <SessionContext.Provider value={value}>{children}</SessionContext.Provider>;
}