State Management Patterns
Overview
State design is one of the highest-leverage architecture choices in Vue apps. Good boundaries reduce bugs, simplify debugging, and make teams faster.
State Categories
Local component state
Short-lived UI concerns: modal visibility, input drafts, temporary toggles.
Shared domain state
Business entities reused across screens: user profile, cart, billing plans.
Server state
Remote data with loading, error, cache invalidation, and refresh semantics.
Pinia Patterns
Store shape by feature
export const useBillingStore = defineStore('billing', {
state: () => ({ plans: [], activePlanId: null, loading: false }),
actions: {
async loadPlans() {
this.loading = true
try {
this.plans = await billingApi.listPlans()
} finally {
this.loading = false
}
}
}
})
Derived getters
Use getters for computed domain projections instead of duplicating state fields.
Synchronization and Cache Strategy
Refresh triggers
- Route entry or explicit user actions.
- Background refresh after mutation success.
- Manual invalidation when backend contracts change.
Optimistic updates
Use optimistic updates only when rollback logic is implemented and UX risk is acceptable.
Learning Objectives
- Separate server state, client state, and derived state.
- Build store modules per business domain.
- Use caching and invalidation strategies.
Common Mistakes
- One giant global store combining unrelated features.
- Duplicating server data across local refs and stores without ownership rules.
- Mutations with side effects that are hard to replay or test.
Engineering Notes
Require a short state map in feature PRs: what state is local, what is shared, what comes from server, and how invalidation works.
Practice Scope
Deliver one production-style mini-feature, include implementation notes, and record one performance, reliability, or maintainability trade-off in your commit summary.
Back to roadmap: Vue Roadmap