State Management
O template usa Zustand para estado client-side e React Router loaders para dados server-side.
Zustand Stores
auth.ts
interface AuthState {
token: string | null;
user: AuthUser | null;
userInfo: AuthUserInfo | null;
isAuthenticated: boolean;
authModal: 'login' | 'register' | null;
refreshState: TokenRefreshState;
setAuth(token: string, user: AuthUser, userInfo: AuthUserInfo): void;
clearAuth(): void;
setAuthModal(modal: 'login' | 'register' | null): void;
hydrateFromCookie(): void;
checkTokenRefresh(callback: () => Promise<void>): void;
}
Principais ações:
setAuth()— salva token + user + userInfo, marcaisAuthenticated: trueclearAuth()— limpa tudo, deleta cookiehydrateFromCookie()— lê token do cookie e seta no storesetAuthModal()— controla qual modal está aberto
layout.ts
interface LayoutState {
mobileMenuOpen: boolean;
setMobileMenuOpen(open: boolean): void;
toggleMobileMenu(): void;
}
React Router Loaders (server-side)
Dados que vêm do server (brand, clientEnv) são carregados via loader e passados via props/context. Não ficam no Zustand.
// _layout.tsx
export async function loader({ context }: Route.LoaderArgs) {
const brand = await loadBrandConfig(env);
const clientEnv = { ... };
return { brand, clientEnv };
}
Padrão de acesso
- Server data (brand, config):
useBrand(),useClientEnv()— via React Context - Client state (auth, layout):
useAuthStore(),useLayoutStore()— via Zustand - Modais: controlados por
authModalno auth store — qualquer componente pode abrir/fechar