Files
flyer-crawler.projectium.com/docs/adr/0005-frontend-state-management-and-server-cache-strategy.md
Torben Sorensen 46c1e56b14
Some checks failed
Deploy to Test Environment / deploy-to-test (push) Failing after 46s
progress enforcing adr-0005
2026-01-08 21:40:20 -08:00

163 lines
9.0 KiB
Markdown

# ADR-005: Frontend State Management and Server Cache Strategy
**Date**: 2025-12-12
**Implementation Date**: 2026-01-08
**Status**: Accepted and Implemented (Phases 1-5 complete, user + admin features migrated)
## Context
The frontend currently uses React's built-in hooks (`useState`, `useEffect`, `useContext`) for state management, as seen in `useAuth.tsx`. While effective for simple cases, this manual approach becomes complex and error-prone when fetching, caching, and synchronizing data with the server. It often leads to custom logic for loading states, errors, re-fetching, and optimistic updates.
## Decision
We will adopt a dedicated library for managing server state, such as **TanStack Query (formerly React Query)** or **SWR**, for all server-side data fetching on the client. This will abstract away the complexities of caching, background re-validation, and request deduplication.
## Consequences
**Positive**: Leads to a more performant, predictable, and simpler frontend codebase. Standardizes how the client-side communicates with the server and handles loading/error states. Improves user experience through intelligent caching.
**Negative**: Introduces a new frontend dependency. Requires a learning curve for developers unfamiliar with the library. Requires refactoring of existing data-fetching logic.
## Implementation Status
### Phase 1: Infrastructure & Core Queries (✅ Complete - 2026-01-08)
**Files Created:**
- [src/config/queryClient.ts](../../src/config/queryClient.ts) - Global QueryClient configuration
- [src/hooks/queries/useFlyersQuery.ts](../../src/hooks/queries/useFlyersQuery.ts) - Flyers data query
- [src/hooks/queries/useWatchedItemsQuery.ts](../../src/hooks/queries/useWatchedItemsQuery.ts) - Watched items query
- [src/hooks/queries/useShoppingListsQuery.ts](../../src/hooks/queries/useShoppingListsQuery.ts) - Shopping lists query
**Files Modified:**
- [src/providers/AppProviders.tsx](../../src/providers/AppProviders.tsx) - Added QueryClientProvider wrapper
- [src/providers/FlyersProvider.tsx](../../src/providers/FlyersProvider.tsx) - Refactored to use TanStack Query
- [src/providers/UserDataProvider.tsx](../../src/providers/UserDataProvider.tsx) - Refactored to use TanStack Query
- [src/services/apiClient.ts](../../src/services/apiClient.ts) - Added pagination params to fetchFlyers
**Benefits Achieved:**
- ✅ Removed ~150 lines of custom state management code
- ✅ Automatic caching of server data
- ✅ Background refetching for stale data
- ✅ React Query Devtools available in development
- ✅ Automatic data invalidation on user logout
- ✅ Better error handling and loading states
### Phase 2: Remaining Queries (✅ Complete - 2026-01-08)
**Files Created:**
- [src/hooks/queries/useMasterItemsQuery.ts](../../src/hooks/queries/useMasterItemsQuery.ts) - Master grocery items query
- [src/hooks/queries/useFlyerItemsQuery.ts](../../src/hooks/queries/useFlyerItemsQuery.ts) - Flyer items query
**Files Modified:**
- [src/providers/MasterItemsProvider.tsx](../../src/providers/MasterItemsProvider.tsx) - Refactored to use TanStack Query
- [src/hooks/useFlyerItems.ts](../../src/hooks/useFlyerItems.ts) - Refactored to use TanStack Query
**Benefits Achieved:**
- ✅ Removed additional ~50 lines of custom state management code
- ✅ Per-flyer item caching (items cached separately for each flyer)
- ✅ Longer cache times for infrequently changing data (master items)
- ✅ Automatic query disabling when dependencies are not met
### Phase 3: Mutations (✅ Complete - 2026-01-08)
**Files Created:**
- [src/hooks/mutations/useAddWatchedItemMutation.ts](../../src/hooks/mutations/useAddWatchedItemMutation.ts) - Add watched item mutation
- [src/hooks/mutations/useRemoveWatchedItemMutation.ts](../../src/hooks/mutations/useRemoveWatchedItemMutation.ts) - Remove watched item mutation
- [src/hooks/mutations/useCreateShoppingListMutation.ts](../../src/hooks/mutations/useCreateShoppingListMutation.ts) - Create shopping list mutation
- [src/hooks/mutations/useDeleteShoppingListMutation.ts](../../src/hooks/mutations/useDeleteShoppingListMutation.ts) - Delete shopping list mutation
- [src/hooks/mutations/useAddShoppingListItemMutation.ts](../../src/hooks/mutations/useAddShoppingListItemMutation.ts) - Add shopping list item mutation
- [src/hooks/mutations/useUpdateShoppingListItemMutation.ts](../../src/hooks/mutations/useUpdateShoppingListItemMutation.ts) - Update shopping list item mutation
- [src/hooks/mutations/useRemoveShoppingListItemMutation.ts](../../src/hooks/mutations/useRemoveShoppingListItemMutation.ts) - Remove shopping list item mutation
- [src/hooks/mutations/index.ts](../../src/hooks/mutations/index.ts) - Barrel export for all mutation hooks
**Benefits Achieved:**
- ✅ Standardized mutation pattern across all data modifications
- ✅ Automatic cache invalidation after successful mutations
- ✅ Built-in success/error notifications
- ✅ Consistent error handling
- ✅ Full TypeScript type safety
- ✅ Comprehensive documentation with usage examples
**See**: [plans/adr-0005-phase-3-summary.md](../../plans/adr-0005-phase-3-summary.md) for detailed documentation
### Phase 4: Hook Refactoring (✅ Complete - 2026-01-08)
**Files Modified:**
- [src/hooks/useWatchedItems.tsx](../../src/hooks/useWatchedItems.tsx) - Refactored to use mutation hooks
- [src/hooks/useShoppingLists.tsx](../../src/hooks/useShoppingLists.tsx) - Refactored to use mutation hooks
- [src/contexts/UserDataContext.ts](../../src/contexts/UserDataContext.ts) - Removed deprecated setters
- [src/providers/UserDataProvider.tsx](../../src/providers/UserDataProvider.tsx) - Removed setter stub implementations
**Benefits Achieved:**
- ✅ Removed 52 lines of code from custom hooks (-17%)
- ✅ Eliminated all `useApi` dependencies from user-facing hooks
- ✅ Removed 150+ lines of manual state management
- ✅ Simplified useShoppingLists by 21% (222 → 176 lines)
- ✅ Maintained backward compatibility for hook consumers
- ✅ Cleaner context interface (read-only server state)
**See**: [plans/adr-0005-phase-4-summary.md](../../plans/adr-0005-phase-4-summary.md) for detailed documentation
### Phase 5: Admin Features (✅ Complete - 2026-01-08)
**Files Created:**
- [src/hooks/queries/useActivityLogQuery.ts](../../src/hooks/queries/useActivityLogQuery.ts) - Activity log query with pagination
- [src/hooks/queries/useApplicationStatsQuery.ts](../../src/hooks/queries/useApplicationStatsQuery.ts) - Application statistics query
- [src/hooks/queries/useSuggestedCorrectionsQuery.ts](../../src/hooks/queries/useSuggestedCorrectionsQuery.ts) - Corrections query
- [src/hooks/queries/useCategoriesQuery.ts](../../src/hooks/queries/useCategoriesQuery.ts) - Categories query (public endpoint)
**Files Modified:**
- [src/pages/admin/ActivityLog.tsx](../../src/pages/admin/ActivityLog.tsx) - Refactored to use TanStack Query
- [src/pages/admin/AdminStatsPage.tsx](../../src/pages/admin/AdminStatsPage.tsx) - Refactored to use TanStack Query
- [src/pages/admin/CorrectionsPage.tsx](../../src/pages/admin/CorrectionsPage.tsx) - Refactored to use TanStack Query
**Benefits Achieved:**
- ✅ Removed 121 lines from admin components (-32%)
- ✅ Eliminated manual state management from all admin queries
- ✅ Automatic parallel fetching (CorrectionsPage fetches 3 queries simultaneously)
- ✅ Consistent caching strategy across all admin features
- ✅ Smart refetching with appropriate stale times (30s to 1 hour)
- ✅ Shared cache across components (useMasterItemsQuery reused)
**See**: [plans/adr-0005-phase-5-summary.md](../../plans/adr-0005-phase-5-summary.md) for detailed documentation
### Phase 6: Cleanup (🔄 In Progress - 2026-01-08)
**Completed:**
- ✅ Removed custom useInfiniteQuery hook (not used in production)
- ✅ Analyzed remaining useApi/useApiOnMount usage
**Remaining:**
- ⏳ Migrate auth features (AuthProvider, AuthView, ProfileManager) from useApi to TanStack Query
- ⏳ Migrate useActiveDeals from useApi to TanStack Query
- ⏳ Migrate AdminBrandManager from useApiOnMount to TanStack Query
- ⏳ Consider removal of useApi/useApiOnMount hooks once fully migrated
- ⏳ Update all tests for migrated features
**Note**: `useApi` and `useApiOnMount` are still actively used in 6 production files for authentication, profile management, and some admin features. Full migration of these critical features requires careful planning and is documented as future work.
## Migration Status
Current Coverage: **85% complete**
-**User Features: 100%** - All core user-facing features fully migrated (queries + mutations + hooks)
-**Admin Features: 100%** - Activity log, stats, corrections now use TanStack Query
-**Auth/Profile Features: 0%** - Auth provider, profile manager still use useApi
-**Analytics Features: 0%** - Active Deals need migration
-**Brand Management: 0%** - AdminBrandManager still uses useApiOnMount
See [plans/adr-0005-master-migration-status.md](../../plans/adr-0005-master-migration-status.md) for complete tracking of all components.
## Implementation Guide
See [plans/adr-0005-implementation-plan.md](../../plans/adr-0005-implementation-plan.md) for detailed implementation steps.