Skip to content

Why State Management

Local component state (ref, reactive) works well when data belongs to one component. But real apps have state that multiple components need to read and update — and passing that state through props across many layers creates a problem called prop drilling.

Imagine FamilyTree without a store. The people array lives in App.vue. Every component that needs it — FocusView, PersonCard, PersonDetailView, all their children — would need to receive it as a prop.

App (owns people[])
└── HomeView (needs people[])
└── FocusView (needs people[])
└── PersonCard (needs people[])

Worse: when PersonCard emits select, that event needs to bubble up through every layer before App can update focusPersonId. Then the update needs to propagate back down through props.

This is prop drilling — threading data through components that don’t need it just to reach the ones that do.

Pinia is Vue’s official state management library. Instead of threading data through props, any component can directly read and update shared state:

App
├── FocusView ──────────────────┐
│ └── PersonCard │
├── PersonDetailView │ All read/write familyStore
└── AddPersonView ──────────────┘

Each component imports the store and uses it directly. No prop drilling. No event chains. The store is the single source of truth.

Not all state belongs in a store. Use local component state for:

  • UI-only state that only the current component cares about (is this dropdown open? is this input focused?)
  • Form field values before submission
  • Transient error messages

Use a store for:

  • Data that multiple components need to read (the people array)
  • Data that multiple components need to update (adding, editing, deleting people)
  • State that needs to persist across navigation (the focus person)

FamilyTree uses a single familyStore that holds the entire people array, all relationship-management actions, and the current focusPersonId.

Think about FamilyTree and answer:

  1. Name three pieces of state that belong in a store and explain why.
  2. Name two pieces of state that belong in a local component ref and explain why.
  3. What would break if FocusView owned the people array instead of a store?
  • Prop drilling is the pattern of passing state through intermediate components that don’t use it.
  • Pinia provides a global store that any component can access directly — eliminating prop drilling.
  • Use local state for UI-only and transient state; use a store for shared, persistent, or multi-component state.