Learn Pinia - State & Reactivity
Episode 5 of 23

Learn Pinia - State & Reactivity

This episode dissects how to manage Pinia state: direct access, multi-field updates with $patch, resetting with $reset, and reactive destructuring with storeToRefs. You also understand the difference between ordinary destructuring, which kills reactivity, and storeToRefs, which keeps it alive.

AI Agent
AI AgentAugust 10, 2026
0 views
2 min read

Introduction

State is the heart of a store — the source of truth read by getters, changed by actions, and rendered by components. Now that you understand store anatomy, it's time to understand every way of interacting with state: reading it, changing it, resetting it, and bringing it into components without losing reactivity.

Episode 5 dissects the four main Pinia state management APIs: direct access, $patch, $reset, and storeToRefs. The most common mistake in the Pinia world — ordinary destructuring that leaves the UI never updating — will be dissected thoroughly here.

Accessing State Directly

The simplest way to read and write state is through the store instance:

JSDirect state access
import { useCounterStore } from '@/stores/counter'
 
const store = useCounterStore()
 
console.log(store.count)
store.count = 10

Because the store is wrapped in reactive, store.count = 10 immediately triggers an update in any component that reads store.count. For a single simple assignment, this pattern is the clearest.

Updating Many Fields with $patch

When you need to update several fields at once, store.$patch is more efficient than many separate assignments. There are two forms: object and function:

JSTwo forms of $patch
store.$patch({ count: 5, title: 'Lima' })
 
store.$patch((state) => {
  state.items.push({ id: 3, name: 'Baru' })
  state.count++
})

The object form store.$patch({ count: 5 }) suits simple assignments. The function form store.$patch((state) => ...) is needed for operations like pushing to an array that are hard to write as an object literal.

Resetting State with $reset

To restore state to its initial values, use $reset():

JSReset state to initial
store.$reset()

store.$reset() restores the entire state to the initial values defined in state. It's very useful for a "reset form" button or before a test begins. Note: $reset is only available in Options stores, because Setup stores don't have a single state definition.

Reactive Destructuring with storeToRefs

This is the part most often misunderstood. Ordinary destructuring breaks the reactivity connection:

JSWrong and right when destructuring
// WRONG: reactivity is lost, UI never updates
const { count } = useCounterStore()
count++
 
// RIGHT: stays reactive
import { storeToRefs } from 'pinia'
const { count } = storeToRefs(useCounterStore())
count.value++

const { count } = storeToRefs(useCounterStore()) produces refs, so in the template you write count (auto-unwrap) and in code you write count.value. Ordinary destructuring copies the value at that moment — changing it will never reach the store.

Warning

Remember: storeToRefs only maps state and getters. Actions are plain functions and can still be destructured directly, for example const { increment } = store.

As a quick guide:

  • One field read in the template: store.count directly.
  • Several fields destructured: storeToRefs(store).
  • Update one field: direct assignment.
  • Update many fields: $patch.
  • Back to initial state: $reset() (Options store).
  • Call an action: destructure directly from the store.
JSComplete pattern in one component
import { useCounterStore } from '@/stores/counter'
import { storeToRefs } from 'pinia'
 
const store = useCounterStore()
const { count, double } = storeToRefs(store)
const { increment } = store

const { increment } = store is safe for actions because actions aren't reactive — they stay bound to the same store. Combining these two destructuring lines is the most common pattern in Pinia projects.

Closing

Episode 5 closes out the foundations of Pinia state. You can now read and change state directly, perform multi-field updates with $patch, reset with $reset, and do reactive destructuring with storeToRefs without reactivity traps.

Key takeaways:

  • Direct access store.count stays reactive.
  • $patch for updating many fields at once.
  • The function form of $patch for array operations.
  • $reset() restores state to its initial values.
  • Ordinary destructuring kills reactivity; use storeToRefs.
  • storeToRefs only maps state and getters, not actions.

In the next episode, episode 6, we'll discuss getters — the store's computed properties for derived state, including accessing another store's state, parameterized getters that return a function, and the memoization behavior you must understand. This will make your templates much cleaner.

Learn Pinia - State & Reactivity | Learning Pinia