Date: 2025-01-XX
Accepted
Building async UIs has always been difficult. Navigation hides content behind spinners, search boxes create race conditions as responses arrive out of order, and form submissions require manual state management for every loading flag and error message. Every async operation forces developers to orchestrate the coordination manually.
This isn't a performance problem; it's a coordination problem. React 19 introduces new primitives that solve async coordination declaratively:
useTransition: Tracks pending async work automaticallyuseOptimistic: Provides instant feedback during mutationsSuspense: Handles loading boundaries declarativelyuseDeferredValue: Maintains stable UX during rapid updatesuse(): Makes data fetching declarative- Form Actions: Automatic transition wrapping for form submissions
- Error Boundaries: Catch errors from transitions automatically
The UI Kit was using React 19.2.0, making these primitives available. However, components were still using imperative patterns:
- Manual debounce logic in
SearchForm - Manual loading states in
Tablemutations - Manual error handling scattered across components
- No standardized async coordination
We will adopt React 19's async coordination primitives throughout the UI Kit:
-
Replace manual debounce with
useDeferredValueinSearchForm- Removes custom debounce implementation
- React automatically coordinates updates
- Input remains responsive while search happens in background
-
Use
useTransitionanduseOptimisticinTablecomponent- Instant UI updates for create/update/delete operations
- Automatic pending state tracking
- Better UX with optimistic updates
-
Implement Form Actions in
CreateNewItemModal- Automatic transition wrapping
- Built-in pending state handling
- Less boilerplate code
-
Create reusable async components:
ErrorBoundary- Catches errors from transitionsSuspenseFallback- Standard loading componentuseAsyncData- Utility for declarative data fetchingTableWithSuspense- Table wrapped with SuspenseTableWithErrorBoundary- Table wrapped with ErrorBoundary
-
Maintain backward compatibility
- All changes are additive
- Existing API remains unchanged
- New components are optional wrappers
Props:
- Less code: React coordinates async operations automatically
- Better UX: Instant feedback through optimistic updates
- Fewer bugs: Automatic coordination prevents race conditions
- Modern approach: Using latest React capabilities
- Consistent patterns: Standardized async handling across components
- Better developer experience: Less boilerplate, more declarative code
Cons:
- Learning curve: Team needs to understand React 19 patterns
- Migration effort: Existing code using old patterns needs updating
- Dependency: Requires React 19+ (already satisfied)
Components Updated:
-
SearchForm (
src/ui/SearchForm/SearchForm.tsx)- Replaced manual debounce with
useDeferredValue - Added
useTransitionfor submit actions - Shows pending state during transitions
- Replaced manual debounce with
-
Table (
src/ui/Table/Table.tsx)- Added
useOptimisticfor instant UI updates - Wrapped mutations in
useTransition - Automatic pending state tracking
- Added
-
CreateNewItemModal (
src/ui/Table/CreateNewItemModal/CreateNewItemModal.tsx)- Implemented Form Actions API
- Automatic transition wrapping
- Built-in pending state
New Components:
- ErrorBoundary (
src/ui/ErrorBoundary/ErrorBoundary.tsx) - SuspenseFallback (
src/ui/SuspenseFallback/SuspenseFallback.tsx) - useAsyncData (
src/utils/useAsyncData.ts) - TableWithSuspense (
src/ui/Table/TableWithSuspense.tsx) - TableWithErrorBoundary (
src/ui/Table/TableWithErrorBoundary.tsx)
Testing:
- All new components have comprehensive tests
- Test coverage: 98.86%
- 68 tests, all passing
Documentation:
- README updated with React 19 section