Skip to content

Standardize client data fetching with a shared, cancelable useApiResource hook #1137

Description

@RUKAYAT-CODER

Background
The panel components all fetch through apiClient but each unwraps the response differently and handles the lifecycle inconsistently. src/components/ai/SmartNotifications.tsx reads res.data, src/components/ai/PersonalizedRecommendations.tsx reads r.items, src/components/ai/NaturalLanguageQuery.tsx reads r.results, and src/components/ai/LearningAssistant.tsx reads r.reply, while src/components/ai/IntelligentProgress.tsx and src/components/social/FollowingSystem.tsx read the payload directly. Only SmartNotifications guards against setState-after-unmount; the others can update unmounted components, and none pass an AbortSignal even though src/lib/api.ts (RequestConfig extends RequestInit) and src/hooks/useAbortController.ts already support cancellation. src/types/api.ts defines ApiResponse but it is applied inconsistently, so each panel reinvents its own loading/error state.

Implementation Plan

  • Add a shared hook src/hooks/useApiResource.ts that wraps apiClient, threads an AbortController (leveraging src/hooks/useAbortController.ts), exposes { data, loading, error, refetch }, and unwraps the canonical ApiResponse envelope consistently.
  • Ensure src/lib/api.ts forwards a caller-supplied signal (composed with its internal timeout controller) and document the canonical response envelope in src/types/api.ts.
  • Adopt the hook in SmartNotifications.tsx, PersonalizedRecommendations.tsx, NaturalLanguageQuery.tsx, LearningAssistant.tsx, IntelligentProgress.tsx, social/FollowingSystem.tsx, and ExportButton.tsx, removing the bespoke useEffect/fetch logic and per-file loading/error state.
  • Add benchmarks/metrics capturing before/after (e.g. dropped-request counts and unmount-safety).
  • Add regression tests.
  • Document the change.

Files in Scope (10)
src/hooks/useApiResource.ts (new), src/lib/api.ts, src/types/api.ts, src/components/ai/SmartNotifications.tsx, src/components/ai/PersonalizedRecommendations.tsx, src/components/ai/NaturalLanguageQuery.tsx, src/components/ai/LearningAssistant.tsx, src/components/ai/IntelligentProgress.tsx, src/components/social/FollowingSystem.tsx, src/components/ExportButton.tsx

Acceptance Criteria

  • Measurable performance/efficiency improvement demonstrated with before/after numbers
  • No regression in existing functionality
  • Tests pass and code follows project standards
  • Change is documented

Difficulty
Medium-Hard

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions