dak.c2s/docs/plans/2026-02-26-state-management-design.md
CCS Admin d4420500e5 docs: add state management refactoring design (TanStack Query)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 18:11:55 +00:00

3.6 KiB

State Management Refactoring — Design

Ziel

Boilerplate reduzieren und Zukunftssicherheit schaffen durch Einführung von TanStack Query für Server-State-Management. UI-State bleibt bei useState/Context.

Ansatz

TanStack Query (@tanstack/react-query) übernimmt alles was mit API-Daten zu tun hat: Fetching, Caching, Refetch, Mutations mit automatischer Cache-Invalidierung.

Architektur

Provider-Hierarchie

App.tsx
└── QueryClientProvider  (NEU)
    └── AuthProvider     (bleibt)
        └── BrowserRouter
            └── Routes...

Globale Query-Konfiguration

  • staleTime: 30s — Daten gelten 30 Sekunden als frisch
  • retry: 1 — Einmal wiederholen bei Fehler
  • refetchOnWindowFocus: false — Kein automatischer Refetch bei Tab-Wechsel

Was migriert wird

Alle useEffect(() => api.get(...), [deps]) Patterns → useQuery() Alle api.put/post in Save-Handlern → useMutation() mit Cache-Invalidierung useNotifications Polling → useQuery() mit refetchInterval: 60000

Was bleibt

  • AuthContext (Token + User)
  • useTheme
  • UI-State (Modals, Sidebar-Toggle, Filter-Inputs) — useState
  • useInlineEdit — bleibt als Hook, nutzt aber TanStack Mutations intern

Custom Query-Hooks

Domänenspezifische Hooks in frontend/src/hooks/:

Hook Ersetzt Datei
useCases(filters) useState+useEffect in CasesPage hooks/useCases.ts
useCase(id) Einzelfall-Fetch in CaseDetail hooks/useCases.ts
useCaseMutation() api.put in useInlineEdit hooks/useCases.ts
useDashboard(jahr) useState+useEffect in DashboardPage hooks/useDashboard.ts
useNotifications() Bestehender Polling-Hook hooks/useNotifications.ts
useUsers() useState+useEffect in AdminUsersPage hooks/useUsers.ts
useDisclosures(status) useState+useEffect in DisclosuresPage hooks/useDisclosures.ts
useAuditLog(filters) useState+useEffect in AdminAuditPage hooks/useAuditLog.ts
useImportLogs(page) useState+useEffect in ImportLogTab hooks/useImportLogs.ts

Query Key Konvention

  • ['cases'] — alle Fälle
  • ['cases', { page, search, jahr, fallgruppe }] — gefilterte Liste
  • ['cases', id] — Einzelfall
  • ['dashboard', jahr] — Dashboard-KPIs
  • ['notifications'] — Benachrichtigungen
  • ['users'] — Admin-Benutzerliste
  • ['disclosures', status] — Disclosure-Anfragen
  • ['audit-log', filters] — Audit-Log
  • ['import-logs', page] — Import-Logs

Mutations & Cache-Invalidierung

Mutation Invalidiert
Case updaten ['cases']
KVNR setzen ['cases']
ICD setzen ['cases'], ['dashboard']
Coding setzen ['cases'], ['dashboard']
Disclosure genehmigen/ablehnen ['disclosures'], ['notifications']
Notification lesen ['notifications']
User anlegen/bearbeiten ['users']

useInlineEdit nutzt intern useMutation() statt direkter api.put(). Der onCaseSaved-Callback durch den Komponentenbaum entfällt komplett.

Migrations-Strategie

Schrittweise Migration, Page für Page:

Phase 1: Setup

  • pnpm add @tanstack/react-query @tanstack/react-query-devtools
  • QueryClientProvider in App.tsx

Phase 2: Einfache Pages

  • DashboardPage, ReportsPage, AdminAuditPage, DisclosuresPage

Phase 3: Mittlere Komplexität

  • AdminUsersPage, ImportLogTab, useNotifications

Phase 4: CasesPage (komplexeste)

  • useCases, useCaseMutation, useKvnrMutation, useIcdMutation
  • useInlineEdit intern auf Mutations umstellen
  • onCaseSaved-Callback entfernen