Using Stores in Components
Using a Pinia store in a component is straightforward: call the store composable and access state, getters, and actions directly on the returned object.
Basic usage
Section titled “Basic usage”<script setup lang="ts">import { useFamilyStore } from '../stores/familyStore'
const store = useFamilyStore()</script>
<template> <p>People: {{ store.people.length }}</p> <p v-if="store.focusPerson">Focused: {{ store.focusPerson.name }}</p> <button @click="store.setFocus('abc-123')">Set focus</button></template>store.people is reactive — when it changes, the template re-renders. store.setFocus() calls the action.
storeToRefs for destructuring
Section titled “storeToRefs for destructuring”Destructuring a Pinia store loses reactivity for state and getters:
// ❌ Breaks reactivity — people is now a plain arrayconst { people, focusPerson } = useFamilyStore()storeToRefs fixes this — it wraps state and getters in refs, preserving reactivity:
import { storeToRefs } from 'pinia'
const store = useFamilyStore()const { people, focusPerson, parents, children, currentSpouse } = storeToRefs(store)Now people, focusPerson, etc. are reactive refs. Use them directly in the template (auto-unwrapped) or with .value in script.
Actions don’t need storeToRefs — they’re plain functions:
const { addPerson, deletePerson, setFocus } = store // ✅ actions are fineIn FamilyTree
Section titled “In FamilyTree”FocusView.vue uses the store for all rendered data:
<script setup lang="ts">import { useFamilyStore } from '../../stores/familyStore'
const store = useFamilyStore()</script>
<template> <PersonCard v-for="parent in store.parents" :key="parent.id" :person="parent" role="parent" :clickable="true" @select="store.setFocus" />
<PersonCard :person="store.focusPerson" role="focus" />
<PersonCard v-if="store.currentSpouse" :person="store.currentSpouse" role="spouse" :clickable="true" @select="store.setFocus" /></template>PersonDetailView.vue uses storeToRefs to destructure the people ref, then computes locally:
const store = useFamilyStore()const { people } = storeToRefs(store)
const person = computed(() => people.value.find(p => p.id === id))One store per concern
Section titled “One store per concern”FamilyTree uses a single store, but larger apps often have multiple stores — one for authentication, one for the cart, one for notifications. Each store is independent and can be used in any component.
Exercise
Section titled “Exercise”- Import
useFamilyStorein a component. - Use
storeToRefsto destructurepeopleandfocusPerson. - Render
focusPerson.name(with av-ifguard) and the count ofpeople. - Add a button that calls
store.addPerson({ name: 'Test', ... })and verify the count increases.
- Call
useStoreName()in<script setup>to get the store instance. - Access state, getters, and actions directly on the store object — all reactive.
- Use
storeToRefs(store)to destructure state and getters while preserving reactivity. - Destructure actions directly from the store — functions don’t lose reactivity.