# WellNuo Stores State management using Zustand for performant, scalable React state. ## Why Zustand? Zustand provides several advantages over Context API: 1. **Better Performance** - Only components using specific values re-render 2. **Simpler API** - No provider wrappers needed 3. **TypeScript First** - Excellent type inference 4. **Flexible** - Can be used outside React components 5. **Smaller Bundle** - Lightweight library (~1KB) ## Available Stores ### Auth Store (`authStore.ts`) Manages authentication state and user sessions. **Features:** - OTP authentication flow (email → OTP → verify) - Automatic session checking on app start - Auto-logout on 401 unauthorized - User profile management - Optimized selector hooks **Basic Usage:** ```tsx import { useAuthStore, initAuthStore } from '@/stores/authStore'; // 1. Initialize once at app start (in app/_layout.tsx) export default function RootLayout() { useEffect(() => { initAuthStore(); }, []); } // 2. Use in components function MyComponent() { const { user, isAuthenticated, logout } = useAuthStore(); return ( {isAuthenticated ? ( Welcome {user?.firstName} ) : ( Please login )} ); } ``` **Optimized Selectors:** Use selector hooks when you only need specific values - prevents unnecessary re-renders: ```tsx import { useAuthUser, useIsAuthenticated } from '@/stores/authStore'; function UserProfile() { // Only re-renders when user changes const user = useAuthUser(); return {user?.email}; } function LoginButton() { // Only re-renders when isAuthenticated changes const isAuthenticated = useIsAuthenticated(); return isAuthenticated ? : ; } ``` **Authentication Flow:** ```tsx function LoginScreen() { const { checkEmail, requestOtp, verifyOtp, error } = useAuthStore(); // Step 1: Check if email exists const emailResult = await checkEmail('user@example.com'); // Step 2: Request OTP code const otpResult = await requestOtp('user@example.com'); // Step 3: Verify OTP and authenticate const success = await verifyOtp('user@example.com', '123456'); if (success) { // User is now authenticated! // Navigate to dashboard } } ``` **State Updates:** ```tsx function ProfileScreen() { const { updateUser } = useAuthStore(); // Update local state (doesn't call API) updateUser({ firstName: 'John', lastName: 'Doe' }); // To persist to server, also call: await api.updateProfile({ firstName: 'John', lastName: 'Doe' }); } ``` **Outside React:** ```tsx import { useAuthStore } from '@/stores/authStore'; // In utility functions or non-component code function isUserAuthenticated() { return useAuthStore.getState().isAuthenticated; } // Trigger logout from anywhere function forceLogout() { useAuthStore.getState().logout(); } ``` ## Testing All stores have comprehensive test coverage: ```bash # Run all store tests npm test -- stores/ # Run specific store tests npm test -- authStore.test.ts # With coverage npm test -- --coverage stores/ ``` ## Best Practices 1. **Use Selectors** - Prefer `useAuthUser()` over `useAuthStore((state) => state.user)` 2. **Initialize Once** - Call `initAuthStore()` only once at app startup 3. **Granular Subscriptions** - Only subscribe to values you need 4. **Type Safety** - Store is fully typed, use TypeScript benefits 5. **Server Sync** - Remember to call API after updating store state ## Migration from Context If migrating from AuthContext: **Before (Context):** ```tsx const { user, isAuthenticated } = useAuth(); ``` **After (Zustand):** ```tsx const { user, isAuthenticated } = useAuthStore(); ``` The API is almost identical! Main difference: no Provider wrapper needed. ## Adding New Stores Follow the pattern in `authStore.ts`: 1. Define state interface 2. Define actions interface 3. Create store with `create()` 4. Export store and selector hooks 5. Add comprehensive tests 6. Document in this README