(selector?: (state: AuthState) => T): AuthState | T {
+ const context = useContext(AuthContext);
+ if (!context) {
+ throw new Error("useAuth must be used within AuthProvider");
+ }
+ return selector ? context(selector) : context();
+}
+```
+
+**Key Takeaway:**
+- **Always provide explicit return types for public APIs**
+- Use function overloads for polymorphic functions
+- Document types in JSDoc comments
+
+---
+
+### Pitfall 4.3: Not Using `import type` for Type-Only Imports
+
+**❌ SUBOPTIMAL:**
+```typescript
+import { ReactNode } from 'react'; // Might be bundled even if only used for types
+```
+
+**✅ CORRECT:**
+```typescript
+import type { ReactNode } from 'react'; // Guaranteed to be stripped from bundle
+```
+
+**Key Takeaway:**
+- **Use `import type` for type-only imports**
+- Smaller bundle size
+- Clearer intent
+
+---
+
+## 5. Component Patterns
+
+### Pitfall 5.1: Forgetting Optional Chaining for Nullable Values
+
+**❌ WRONG:**
+```typescript
+function UserProfile() {
+ const { user } = useAuth();
+ return {user.name}
; // ❌ Crashes if user is null
+}
+```
+
+**✅ CORRECT:**
+```typescript
+function UserProfile() {
+ const { user } = useAuth();
+
+ if (!user) {
+ return Not logged in
;
+ }
+
+ return {user.name}
; // ✅ Safe
+}
+
+// OR with optional chaining
+function UserProfile() {
+ const { user } = useAuth();
+ return {user?.name ?? 'Guest'}
; // ✅ Safe
+}
+```
+
+**Key Takeaway:**
+- **Always handle null/undefined cases**
+- Use optional chaining (`?.`) and nullish coalescing (`??`)
+- Provide fallback UI for missing data
+
+---
+
+### Pitfall 5.2: Mixing Concerns in Components
+
+**❌ WRONG:**
+```typescript
+function UserDashboard() {
+ const [users, setUsers] = useState([]);
+ const [loading, setLoading] = useState(false);
+
+ // Data fetching mixed with component logic ❌
+ useEffect(() => {
+ setLoading(true);
+ fetch('/api/users')
+ .then(res => res.json())
+ .then(data => setUsers(data))
+ .finally(() => setLoading(false));
+ }, []);
+
+ // Business logic mixed with rendering ❌
+ const activeUsers = users.filter(u => u.isActive);
+ const sortedUsers = activeUsers.sort((a, b) => a.name.localeCompare(b.name));
+
+ return {/* Render sortedUsers */}
;
+}
+```
+
+**✅ CORRECT:**
+```typescript
+// Custom hook for data fetching
+function useUsers() {
+ return useQuery({
+ queryKey: ['users'],
+ queryFn: () => UserService.getUsers(),
+ });
+}
+
+// Custom hook for business logic
+function useActiveUsersSorted(users: User[] | undefined) {
+ return useMemo(() => {
+ if (!users) return [];
+ return users
+ .filter(u => u.isActive)
+ .sort((a, b) => a.name.localeCompare(b.name));
+ }, [users]);
+}
+
+// Component only handles rendering
+function UserDashboard() {
+ const { data: users, isLoading } = useUsers();
+ const sortedUsers = useActiveUsersSorted(users);
+
+ if (isLoading) return ;
+
+ return {/* Render sortedUsers */}
;
+}
+```
+
+**Key Takeaway:**
+- **Separate concerns: data fetching, business logic, rendering**
+- Extract logic to custom hooks
+- Keep components focused on UI
+
+---
+
+## 6. Provider Architecture
+
+### Pitfall 6.1: Wrong Provider Order
+
+**❌ WRONG:**
+```typescript
+// AuthInitializer outside AuthProvider ❌
+function RootLayout({ children }) {
+ return (
+
+ {/* Can't access auth context! */}
+
+ {children}
+
+
+ );
+}
+```
+
+**✅ CORRECT:**
+```typescript
+function RootLayout({ children }) {
+ return (
+ {/* Provider first */}
+ {/* Can access auth context */}
+
+ {children}
+
+
+ );
+}
+```
+
+**Key Takeaway:**
+- **Providers must wrap components that use them**
+- Order matters when there are dependencies
+- Keep provider tree shallow (performance)
+
+---
+
+### Pitfall 6.2: Creating Too Many Providers
+
+**❌ WRONG:**
+```typescript
+// Separate provider for every piece of state ❌
+
+
+
+
+
+
+
+
+
+
+
+```
+
+**✅ BETTER:**
+```typescript
+// Combine related state, use Zustand for most things
+ {/* Only for auth DI */}
+ {/* Built-in from lib */}
+ {/* React Query */}
+
+
+
+
+
+// Most other state in Zustand stores (no providers needed)
+const useUIStore = create(...); // Theme, sidebar, modals
+const useUserPreferences = create(...); // User settings
+```
+
+**Key Takeaway:**
+- **Use Context only when necessary** (DI, third-party integrations)
+- **Use Zustand for most global state** (no provider needed)
+- Avoid provider hell
+
+---
+
+## 7. Event Handlers & Callbacks
+
+### Pitfall 7.1: Using Hooks in Event Handlers
+
+**❌ WRONG:**
+```typescript
+function MyComponent() {
+ const handleClick = () => {
+ const { user } = useAuth(); // ❌ Hook called in callback!
+ console.log(user);
+ };
+
+ return ;
+}
+```
+
+**✅ CORRECT:**
+```typescript
+function MyComponent() {
+ const { user } = useAuth(); // ✅ Hook at component top level
+
+ const handleClick = () => {
+ console.log(user); // Access from closure
+ };
+
+ return ;
+}
+
+// OR for mutations, use getState()
+function MyComponent() {
+ const handleLogout = async () => {
+ const clearAuth = useAuthStore.getState().clearAuth; // ✅ Not a hook call
+ await clearAuth();
+ };
+
+ return ;
+}
+```
+
+**Key Takeaway:**
+- **Never call hooks inside event handlers**
+- For render state: Call hook at top level, access in closure
+- For mutations: Use `store.getState().method()`
+
+---
+
+### Pitfall 7.2: Not Handling Async Errors in Event Handlers
+
+**❌ WRONG:**
+```typescript
+const handleSubmit = async (data: FormData) => {
+ await apiCall(data); // ❌ No error handling!
+};
+```
+
+**✅ CORRECT:**
+```typescript
+const handleSubmit = async (data: FormData) => {
+ try {
+ await apiCall(data);
+ toast.success('Success!');
+ } catch (error) {
+ console.error('Failed to submit:', error);
+ toast.error('Failed to submit form');
+ }
+};
+```
+
+**Key Takeaway:**
+- **Always wrap async calls in try/catch**
+- Provide user feedback for both success and errors
+- Log errors for debugging
+
+---
+
+## 8. Testing Pitfalls
+
+### Pitfall 8.1: Not Mocking Context Providers in Tests
+
+**❌ WRONG:**
+```typescript
+// Test without provider ❌
+test('renders user name', () => {
+ render(); // Will crash - no AuthProvider!
+ expect(screen.getByText('John')).toBeInTheDocument();
+});
+```
+
+**✅ CORRECT:**
+```typescript
+// Mock the hook
+jest.mock('@/lib/stores', () => ({
+ useAuth: jest.fn(),
+}));
+
+test('renders user name', () => {
+ (useAuth as jest.Mock).mockReturnValue({
+ user: { id: '1', name: 'John' },
+ isAuthenticated: true,
+ });
+
+ render();
+ expect(screen.getByText('John')).toBeInTheDocument();
+});
+```
+
+**Key Takeaway:**
+- **Mock hooks at module level in tests**
+- Provide necessary return values for each test case
+- Test both success and error states
+
+---
+
+### Pitfall 8.2: Testing Implementation Details
+
+**❌ WRONG:**
+```typescript
+test('calls useAuthStore hook', () => {
+ const spy = jest.spyOn(require('@/lib/stores'), 'useAuthStore');
+ render();
+ expect(spy).toHaveBeenCalled(); // ❌ Testing implementation!
+});
+```
+
+**✅ CORRECT:**
+```typescript
+test('displays user name when authenticated', () => {
+ (useAuth as jest.Mock).mockReturnValue({
+ user: { name: 'John' },
+ isAuthenticated: true,
+ });
+
+ render();
+ expect(screen.getByText('John')).toBeInTheDocument(); // ✅ Testing behavior!
+});
+```
+
+**Key Takeaway:**
+- **Test behavior, not implementation**
+- Focus on what the user sees/does
+- Don't test internal API calls unless critical
+
+---
+
+## 9. Performance
+
+### Pitfall 9.1: Not Using React.memo for Expensive Components
+
+**❌ SUBOPTIMAL:**
+```typescript
+// Re-renders every time parent re-renders ❌
+function ExpensiveChart({ data }) {
+ // Heavy computation/rendering
+ return ;
+}
+```
+
+**✅ OPTIMIZED:**
+```typescript
+// Only re-renders when data changes ✅
+export const ExpensiveChart = React.memo(function ExpensiveChart({ data }) {
+ return ;
+});
+```
+
+**Key Takeaway:**
+- **Use `React.memo` for expensive components**
+- Especially useful for list items, charts, heavy UI
+- Profile with React DevTools to identify candidates
+
+---
+
+### Pitfall 9.2: Creating Functions Inside Render
+
+**❌ SUBOPTIMAL:**
+```typescript
+function MyComponent() {
+ return (
+
+ );
+}
+```
+
+**✅ OPTIMIZED:**
+```typescript
+function MyComponent() {
+ const handleClick = useCallback(() => {
+ console.log('clicked');
+ }, []);
+
+ return ;
+}
+```
+
+**When to Optimize:**
+- **For memoized child components** (memo, PureComponent)
+- **For expensive event handlers**
+- **When profiling shows performance issues**
+
+**When NOT to optimize:**
+- **Simple components with cheap operations** (premature optimization)
+- **One-off event handlers**
+
+**Key Takeaway:**
+- **Use `useCallback` for functions passed to memoized children**
+- But don't optimize everything - profile first
+
+---
+
+## 10. Import/Export Patterns
+
+### Pitfall 10.1: Not Using Barrel Exports
+
+**❌ INCONSISTENT:**
+```typescript
+// Deep imports all over the codebase
+import { useAuth } from '@/lib/auth/AuthContext';
+import { useAuthStore } from '@/lib/stores/authStore';
+import { User } from '@/lib/stores/authStore';
+```
+
+**✅ CONSISTENT:**
+```typescript
+// Barrel exports in stores/index.ts
+export { useAuth, AuthProvider } from '../auth/AuthContext';
+export { useAuthStore, type User } from './authStore';
+
+// Clean imports everywhere
+import { useAuth, useAuthStore, User } from '@/lib/stores';
+```
+
+**Key Takeaway:**
+- **Create barrel exports (index.ts) for public APIs**
+- Easier to refactor internal structure
+- Consistent import paths across codebase
+
+---
+
+### Pitfall 10.2: Circular Dependencies
+
+**❌ WRONG:**
+```typescript
+// fileA.ts
+import { functionB } from './fileB';
+export function functionA() { return functionB(); }
+
+// fileB.ts
+import { functionA } from './fileA'; // ❌ Circular!
+export function functionB() { return functionA(); }
+```
+
+**✅ CORRECT:**
+```typescript
+// utils.ts
+export function sharedFunction() { /* shared logic */ }
+
+// fileA.ts
+import { sharedFunction } from './utils';
+export function functionA() { return sharedFunction(); }
+
+// fileB.ts
+import { sharedFunction } from './utils';
+export function functionB() { return sharedFunction(); }
+```
+
+**Key Takeaway:**
+- **Avoid circular imports**
+- Extract shared code to separate modules
+- Keep dependency graph acyclic
+
+---
+
+## Verification Checklist
+
+Before committing code, always run:
+
+```bash
+# Type checking
+npm run type-check
+
+# Linting
+npm run lint
+
+# Tests
+npm test
+
+# Build check
+npm run build
+```
+
+**In browser:**
+- [ ] No console errors or warnings
+- [ ] Components render correctly
+- [ ] No infinite loops or excessive re-renders (React DevTools)
+- [ ] Proper error handling (test error states)
+
+---
+
+## Additional Resources
+
+- [React Rules of Hooks](https://react.dev/reference/rules/rules-of-hooks)
+- [Zustand Best Practices](https://docs.pmnd.rs/zustand/guides/practice-with-no-store-actions)
+- [TypeScript Best Practices](https://www.typescriptlang.org/docs/handbook/declaration-files/do-s-and-don-ts.html)
+- [Testing Library Best Practices](https://testing-library.com/docs/queries/about#priority)
+
+---
+
+**Last Updated**: 2025-11-03
+**Maintainer**: Development Team
+**Status**: Living Document - Add new pitfalls as they're discovered