ADR-010: Use TanStack Query and React Context for Frontend State Management
Status
Accepted
Date
YYYY-MM-DD
Context
Chilarai requires frontend state management for two fundamentally different categories of data:
Server State
Data that originates from backend APIs.
Examples:
- Students
- Admissions
- Staff
- Attendance
- Fees
- Academic Structure
- School Configuration
Server state requires:
- API communication
- Caching
- Refetching
- Retry handling
- Background updates
- Pagination
- Query invalidation
Application State
Data that exists only within the browser.
Examples:
- Active School Context
- Theme Preferences
- Sidebar State
- UI Preferences
- Current Navigation Context
Application state does not originate from backend APIs.
The architecture should:
- Minimize complexity
- Avoid duplicate state
- Prevent multiple sources of truth
- Remain easy for new developers to understand
- Scale as the application grows
Decision
Chilarai will use:
- TanStack Query for Server State
- React Context for Application State
The platform will not use Redux or Zustand during the initial implementation.
Business data retrieved from APIs must be managed exclusively through TanStack Query.
Application state must be managed through React Context.
Rationale
Clear Separation of Concerns
Server State and Application State have different requirements.
TanStack Query is optimized for data that originates from backend services.
React Context is sufficient for lightweight browser-only state.
This separation creates a clear architectural rule:
Server State → TanStack Query
Application State → React Context
Avoid Multiple Sources of Truth
Duplicating server data into client-side stores creates synchronization problems.
Example:
Student List
Stored In:
- TanStack Query
- Zustand
The application now has two sources of truth.
As data changes, synchronization logic becomes necessary.
This increases complexity and introduces bugs.
To avoid this, API data must never be copied into separate frontend state stores.
Simplicity
React Context is sufficient for the current application state requirements.
Examples:
- Active School
- Theme
- Navigation State
Introducing additional state management libraries would increase the number of architectural concepts without providing significant value.
Modern Server State Management
TanStack Query provides:
- Query Caching
- Background Refetching
- Automatic Retries
- Query Invalidation
- Loading States
- Error Handling
- Pagination Support
These features would otherwise require significant custom implementation.
State Ownership Rules
TanStack Query
Owns:
- Students
- Admissions
- Staff
- Attendance
- Fees
- Academic Data
- School Data
- User Data retrieved from APIs
Examples:
["students"]
["student", studentId]
["admissions"]
["fees", studentId]
TanStack Query is the source of truth for all backend-managed data.
React Context
Owns:
- Active School Context
- Theme
- Sidebar State
- Session UI Preferences
Examples:
SchoolContext
ThemeContext
NavigationContext
React Context is the source of truth for browser-only application state.
School Context Management
The frontend maintains an Active School Context.
Example:
User ↓ School Memberships ↓ Select School ↓ Active School Context
A user may belong to multiple Schools.
The frontend must provide a School Switcher within the application shell.
When the active School changes:
- Context is updated
- Queries are invalidated
- Permissions are refreshed
- Screen data is reloaded
Query Strategy
All API communication must use TanStack Query.
Example:
Student List
useQuery({
queryKey: ["students", schoolId],
queryFn: getStudents
})
The School Context must be included in query keys when applicable.
This ensures proper cache isolation between Schools.
Mutations
All data modifications must use TanStack Query mutations.
Example:
Create Student
useMutation({
mutationFn: createStudent,
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["students"]
});
}
})
Mutations are responsible for refreshing affected queries.
Alternatives Considered
Redux
Pros:
- Single state mechanism
- Mature ecosystem
Cons:
- Significant boilerplate
- Server state concerns become application responsibilities
- Increased complexity for MVP
Decision:
Rejected.
Redux Toolkit + RTK Query
Pros:
- Modern Redux approach
- Strong ecosystem
Cons:
- Additional complexity
- Reduced simplicity compared to TanStack Query
Decision:
Rejected.
Zustand
Pros:
- Lightweight
- Simple API
Cons:
- Creates ambiguity regarding state ownership
- Risk of duplicating server state
- Additional architectural concept
Decision:
Deferred.
May be introduced later if application state becomes significantly more complex.
Consequences
Positive
- Clear ownership of state
- Reduced boilerplate
- Excellent API caching
- Easy onboarding for developers
- Simplified architecture
- Strong support for school context switching
Negative
- Multiple React Context providers may exist
- Zustand may eventually be required if application state grows significantly
Implementation Notes
Example structure:
src
├── app
├── modules
├── shared
├── providers
│ ├── school-context
│ ├── theme-context
│ └── auth-context
│
└── api
TanStack Query should be configured centrally.
React Context providers should be registered at the application shell level.
Business entities must never be copied from TanStack Query into separate state stores.
Decision Summary
Chilarai will use:
- TanStack Query for Server State
- React Context for Application State
Server state and application state have distinct responsibilities and ownership boundaries.
This approach minimizes complexity, avoids duplicate sources of truth, and provides a simple, scalable frontend architecture.