Persisting State
By default, Pinia state is in-memory — it resets when the page is refreshed. For FamilyTree, that would mean losing the entire family tree on every reload. pinia-plugin-persistedstate solves this by serializing store state to localStorage automatically.
Installing the plugin
Section titled “Installing the plugin”npm install pinia-plugin-persistedstateRegister it in main.ts:
import { createApp } from 'vue'import { createPinia } from 'pinia'import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'import App from './App.vue'import router from './router'
const app = createApp(App)const pinia = createPinia()pinia.use(piniaPluginPersistedstate)app.use(pinia)app.use(router)app.mount('#app')Enabling persistence in a store
Section titled “Enabling persistence in a store”Add persist: true as the third argument to defineStore:
export const useFamilyStore = defineStore( 'family', () => { const people = ref<Person[]>([]) // ... return { people, /* ... */ } }, { persist: true })That’s it. On every state change, Pinia serializes the returned state to localStorage under the key 'family'. On page load, it restores the state before any component mounts.
The afterHydrate hook
Section titled “The afterHydrate hook”When persisted data is loaded from localStorage, the plugin’s afterHydrate callback runs. This is the right place to normalize data — for example, if you added a new field to your Person type after users already had data saved.
Without normalization, old Person objects in localStorage won’t have the new field, causing errors when code expects it to exist.
export const useFamilyStore = defineStore( 'family', () => { const people = ref<Person[]>([]) // ... return { people } }, { persist: { afterHydrate: (ctx) => { // Ensure all Person objects have required array fields // (handles data saved before these fields were added) ctx.store.$patch({ people: (ctx.store.people as any[]).map((p: any) => ({ parentIds: [], stepParentIds: [], spouses: [], siblingIds: [], ...p, // existing values override defaults })), }) }, }, })This pattern saved FamilyTree when stepParentIds and spouses were added — users who had data saved without those fields got them auto-normalized instead of seeing a TypeError.
What gets persisted
Section titled “What gets persisted”By default, everything returned from the store setup is persisted. You can configure pick or omit to select specific keys:
{ persist: { pick: ['people', 'focusPersonId'] } }Exercise
Section titled “Exercise”- Install
pinia-plugin-persistedstateand register it inmain.ts. - Add
{ persist: true }to your counter store. - Increment the counter a few times, then refresh the page. Confirm the count survives.
- Open DevTools → Application → localStorage to see the serialized data.
pinia-plugin-persistedstateauto-serializes store state to localStorage.- Register with
pinia.use(piniaPluginPersistedstate)and add{ persist: true }to the store. afterHydrateruns after state is restored — use it to normalize stale persisted data.- Use
pickoromitto control which state keys are persisted.