2.7 KiB
<AuthProvider> and useAuth / useUser / useIsAuthenticated
Purpose
auth-context.tsx ships the <AuthProvider> React context provider together
with the three hooks useAuth, useUser, and useIsAuthenticated. The
provider wires a tenant-aware auth backend through an injectable fetch
(FetchLike) and an injectable navigate(url) seam so consumers can plug
real backends in production and stub them in tests without vi.mock. Every
verb — login, loginWithProvider, register, logout,
requestPasswordReset, resetPassword — is surfaced on the context value
returned by useAuth() and translates HTTP failures into stable, code-tagged
errors via ReactAuthWhitelabelError.
Features
- Injectable
fetch: FetchLikefor testability — defaults toglobalThis.fetch. - Injectable
navigate(url)seam — defaults towindow.location.href = urlin browsers, no-op in non-browser environments. - Session probe on mount unless
initialUseris supplied (SSR/hydration). - Network failures →
REACT_AUTH_WL.AUTH_NETWORK_FAILED. - Non-ok responses →
REACT_AUTH_WL.AUTH_REJECTEDwith the backend'smessagefield threaded through when present. - Hooks called outside the provider throw
REACT_AUTH_WL.PROVIDER_OUTSIDE_TREE.
Usage: Basic
<AuthProvider config={{ authUrl: "/api/auth" }}>
<App />
</AuthProvider>
const { login, user, isAuthenticated } = useAuth();
await login("a@b.c", "pw");
Usage: Advanced
const config: AuthConfig = {
authUrl: "https://auth.acme.com",
redirectUrl: "/dashboard",
fetch: customFetch, // testable seam
navigate: (url) => router.navigate(url),
providers: [{ id: "google", name: "Google" }],
};
<AuthProvider config={config} initialUser={ssrUser}>
<Routes>...</Routes>
</AuthProvider>
API Reference
AuthProvider({ config, initialUser?, children })— context provider.useAuth()— returnsAuthContextValue(user,isLoading,isAuthenticated,error,login,loginWithProvider,register,logout,requestPasswordReset,resetPassword).useUser()— returnsAuthUser | null.useIsAuthenticated()— returnsboolean.
Implementation Notes
The session probe in useEffect swallows transport errors on purpose — a
session check that fails should not surface as a visible error to the user
(they simply remain anonymous). Verbs called from the UI translate failures
to typed errors AND surface them on the context's error state so a single
error region can render the current failure without each call site
re-implementing the same try/catch. Every verb sets isLoading true/false
around the network call so consumers can disable submit buttons via
isLoading || isSubmitting.