# Vue 3 Pinia vs Vuex: Modern State Management en Sollicitatievragen 2026 > Pinia vs Vuex vergeleken: API-ontwerp, TypeScript-ondersteuning, performance, migratiestrategieën en veelgestelde Vue state management sollicitatievragen voor 2026. - Published: 2026-04-23 - Updated: 2026-04-23 - Author: SharpSkill - Tags: vue, pinia, vuex, state-management, interview - Reading time: 9 min --- Pinia vs Vuex vertegenwoordigt de meest significante verschuiving in Vue state management sinds de lancering van Vue 3. Nu Pinia 3 de officiële aanbeveling is en Vuex alleen nog in onderhoudsmodus wordt beheerd, is het begrijpen van de verschillen tussen beide bibliotheken essentieel voor Vue-ontwikkelaars — en een veelvoorkomend onderwerp tijdens technische sollicitatiegesprekken. > **Kernpunt** > > Pinia is de officiële state management oplossing voor Vue 3. Vuex 5 is geannuleerd, en Evan You heeft Pinia aangeduid als het de facto Vuex 5. Alle nieuwe Vue 3-projecten dienen Pinia 3 te gebruiken. ## Pinia vs Vuex: Fundamentele Architectuurverschillen Het fundamentele architectuurverschil tussen Pinia en Vuex ligt in de manier waarop state-mutaties plaatsvinden. Vuex dwingt een strikte unidirectionele dataflow af: componenten dispatchen actions, actions committen mutations, en mutations wijzigen de state. Pinia verwijdert de mutation-laag volledig en staat directe state-wijzigingen toe vanuit actions of zelfs vanuit componenten. Deze vereenvoudiging vermindert boilerplate-code met ongeveer 40% in de meeste codebases. Waar Vuex vier concepten vereist (state, getters, mutations, actions), werkt Pinia met drie (state, getters, actions). | Kenmerk | Pinia 3 | Vuex 4 | |---------|---------|--------| | Mutations | Geen (directe state-wijzigingen) | Vereist voor state-wijzigingen | | TypeScript | Volledige inferentie, geen augmentation | Handmatige type-augmentation nodig | | Store-architectuur | Meerdere platte stores | Enkele store met geneste modules | | Composition API | Native ondersteuning | Options API gebaseerd | | Bundelgrootte | ~1 KB gzipped | ~6 KB gzipped | | Vue Devtools | Volledige ondersteuning (v7) | Volledige ondersteuning | | SSR | Ingebouwd | Configuratie vereist | | Hot Module Replacement | Ingebouwd | Handmatige setup | ## Stores Definiëren: Options API vs Setup-Syntax Pinia biedt twee syntaxvarianten voor het definiëren van stores. De Options-syntax weerspiegelt de structuur van Vuex, wat migratie vergemakkelijkt. De Setup-syntax benut de Composition API van Vue 3 voor maximale flexibiliteit. ```typescript // stores/counter-options.ts import { defineStore } from 'pinia' // Options Store syntax — vertrouwd voor Vuex-ontwikkelaars export const useCounterStore = defineStore('counter', { state: () => ({ count: 0, lastUpdated: null as Date | null, }), getters: { // Getters ontvangen state als eerste argument met volledige type-inferentie doubleCount: (state) => state.count * 2, isPositive(): boolean { // Toegang tot andere getters via `this` return this.count > 0 }, }, actions: { increment() { // Directe state-mutatie — geen commit() nodig this.count++ this.lastUpdated = new Date() }, async fetchCount(id: string) { // Asynchrone actions werken zonder extra configuratie const response = await fetch(`/api/counters/${id}`) const data = await response.json() this.count = data.count }, }, }) ``` De Options-syntax vertaalt Vuex-concepten rechtstreeks. State vervangt Vuex state, getters blijven getters, en actions nemen zowel Vuex actions als mutations over. ```typescript // stores/counter-setup.ts import { defineStore } from 'pinia' import { ref, computed } from 'vue' // Setup Store syntax — identieke patronen als Composition API export const useCounterStore = defineStore('counter', () => { // ref() wordt state const count = ref(0) const lastUpdated = ref(null) // computed() wordt getters const doubleCount = computed(() => count.value * 2) const isPositive = computed(() => count.value > 0) // Functies worden actions function increment() { count.value++ lastUpdated.value = new Date() } async function fetchCount(id: string) { const response = await fetch(`/api/counters/${id}`) const data = await response.json() count.value = data.count } // Alle state, getters en actions moeten worden geretourneerd return { count, lastUpdated, doubleCount, isPositive, increment, fetchCount } }) ``` De Setup-syntax biedt volledige flexibiliteit: watchers, hergebruik van composables en conditionele logica werken op natuurlijke wijze binnen de store-definitie. De keerzijde is dat elke reactieve eigenschap en methode expliciet moet worden geretourneerd. ## TypeScript-Integratie: Waar Pinia Vuex Overtreft TypeScript-ondersteuning is het gebied waar Pinia overtuigend wint. Vuex 4 vereist handmatige type-augmentation via module-declaraties, en bij complexe geneste modules wordt type-inferentie broos. Pinia leidt types automatisch af uit de store-definitie. ```typescript // Vuex 4 — handmatige type-augmentation vereist import { Store } from 'vuex' declare module 'vuex' { interface State { counter: { count: number lastUpdated: Date | null } } } // Toegang tot state vereist type assertions of aangepaste helpers const count = (store.state as { counter: { count: number } }).counter.count ``` ```typescript // Pinia — volledige type-inferentie, geen configuratie const counter = useCounterStore() // TypeScript herkent counter.count als number // TypeScript herkent counter.doubleCount als number // TypeScript herkent counter.increment() als void // TypeScript herkent counter.fetchCount() als Promise counter.increment() console.log(counter.doubleCount) ``` Pinia ondersteunt bovendien generieke stores voor herbruikbare patronen — een mogelijkheid die aanzienlijke boilerplate vereist in Vuex. ## Composition API en Composable-Integratie Pinia Setup stores accepteren elke Vue composable, wat krachtige patronen mogelijk maakt zoals gedeelde VueUse-utilities of router-bewuste state. ```typescript // stores/search.ts import { defineStore } from 'pinia' import { ref, watch } from 'vue' import { useDebounceFn } from '@vueuse/core' import { useRoute } from 'vue-router' export const useSearchStore = defineStore('search', () => { const route = useRoute() const query = ref('') const results = ref([]) const isLoading = ref(false) // VueUse composable direct in de store gebruikt const debouncedSearch = useDebounceFn(async (term: string) => { if (!term.trim()) { results.value = [] return } isLoading.value = true try { const res = await fetch(`/api/search?q=${encodeURIComponent(term)}`) results.value = await res.json() } finally { isLoading.value = false } }, 300) // Watcher synchroniseert URL query parameter met store state watch(() => route.query.q, (q) => { if (typeof q === 'string') { query.value = q debouncedSearch(q) } }) function setQuery(term: string) { query.value = term debouncedSearch(term) } return { query, results, isLoading, setQuery } }) ``` Dit patroon is onmogelijk in Vuex zonder workarounds. Vuex-modules kunnen geen composables, watchers of router-hooks gebruiken binnen hun definitie. De store-logica moet worden opgesplitst tussen de Vuex-module en externe hulpfuncties. ## Store-Communicatie en Onderlinge Referenties Vuex gebruikt een enkele root-store met namespaced modules. Toegang tot state over modules heen vereist de omslachtige `rootState`- en `rootGetters`-parameters. Pinia stores zijn bewust onafhankelijk ontworpen, en communicatie tussen stores verloopt via directe imports. ```typescript // stores/cart.ts import { defineStore } from 'pinia' import { useProductStore } from './products' import { useAuthStore } from './auth' import { ref, computed } from 'vue' export const useCartStore = defineStore('cart', () => { const items = ref([]) const total = computed(() => { // Toegang tot een andere store door het aanroepen van de composable const productStore = useProductStore() return items.value.reduce((sum, item) => { const product = productStore.getById(item.productId) return sum + (product?.price ?? 0) * item.quantity }, 0) }) async function checkout() { const auth = useAuthStore() if (!auth.isAuthenticated) { throw new Error('Authenticatie vereist') } // Checkout-logica } return { items, total, checkout } }) ``` Deze platte store-architectuur voorkomt de diep geneste module-bomen die grote Vuex-applicaties moeilijk navigeerbaar en refactorbaar maken. ## Migratie van Vuex 4 naar Pinia 3 Migratie van Vuex naar Pinia kan module voor module plaatsvinden. Beide bibliotheken kunnen naast elkaar bestaan gedurende de overgangsperiode. De aanbevolen strategie: begin met blad-modules (stores waar geen andere modules van afhankelijk zijn) en werk naar binnen toe. > **Migratiecompatibiliteit** > > Pinia en Vuex kunnen naast elkaar draaien in dezelfde applicatie. Installeer Pinia naast Vuex, migreer één module tegelijk en verwijder Vuex pas nadat alle modules zijn geconverteerd. ```typescript // Voorheen: Vuex-module // store/modules/user.ts const userModule = { namespaced: true, state: () => ({ profile: null as UserProfile | null, preferences: {} as UserPreferences, }), mutations: { SET_PROFILE(state, profile: UserProfile) { state.profile = profile }, UPDATE_PREFERENCES(state, prefs: Partial) { state.preferences = { ...state.preferences, ...prefs } }, }, actions: { async fetchProfile({ commit }) { const profile = await api.getProfile() commit('SET_PROFILE', profile) }, async updatePreferences({ commit }, prefs: Partial) { await api.updatePreferences(prefs) commit('UPDATE_PREFERENCES', prefs) }, }, getters: { isLoggedIn: (state) => state.profile !== null, displayName: (state) => state.profile?.name ?? 'Guest', }, } ``` ```typescript // Nadien: Pinia store // stores/user.ts import { defineStore } from 'pinia' import { ref, computed } from 'vue' import { api } from '@/lib/api' export const useUserStore = defineStore('user', () => { const profile = ref(null) const preferences = ref({}) const isLoggedIn = computed(() => profile.value !== null) const displayName = computed(() => profile.value?.name ?? 'Guest') async function fetchProfile() { profile.value = await api.getProfile() } async function updatePreferences(prefs: Partial) { await api.updatePreferences(prefs) Object.assign(preferences.value, prefs) } return { profile, preferences, isLoggedIn, displayName, fetchProfile, updatePreferences } }) ``` Het migratiepatroon is consistent: mutations worden samengevoegd tot directe toewijzingen binnen actions, `commit()`-aanroepen verdwijnen, en `mapState`/`mapGetters`-helpers worden vervangen door destructurering van de store-composable. ## SSR State Hydration met Pinia en Nuxt 4 Server-side rendering introduceert complexiteit voor state management. Pinia verzorgt SSR state-serialisatie en hydration automatisch in [Nuxt 4](https://nuxt.com/docs/getting-started/state-management), terwijl Vuex handmatige `window.__INITIAL_STATE__`-afhandeling vereist. > **SSR-Valkuil** > > Setup stores die composables zoals `useRoute()` of `useFetch()` gebruiken, vereisen zorgvuldige afhandeling in SSR-contexten. Deze composables mogen alleen worden aangeroepen tijdens de setup-fase, nooit binnen asynchrone callbacks. ```typescript // stores/products.ts — SSR-veilige Pinia store voor Nuxt 4 import { defineStore } from 'pinia' export const useProductStore = defineStore('products', { state: () => ({ items: [] as Product[], selectedCategory: 'all', }), actions: { async fetchProducts() { // useFetch is Nuxt-specifiek — gebruik $fetch voor store actions this.items = await $fetch('/api/products', { query: { category: this.selectedCategory }, }) }, }, getters: { getById: (state) => (id: string) => state.items.find((item) => item.id === id), filteredCount: (state) => state.items.filter((p) => p.inStock).length, }, }) ``` Nuxt 4 serialiseert de Pinia-state automatisch op de server en hydrateert deze op de client. Geen handmatige `replaceState()`- of dehydratatielogica nodig. ## Performancevergelijking en Bundelimpact De footprint van Pinia van ~1 KB gzipped is ongeveer zes keer kleiner dan de ~6 KB van Vuex. In applicaties met code splitting zijn Pinia stores tree-shakable: ongebruikte stores en hun afhankelijkheden worden uitgesloten van productiebundels. Runtime-performanceverschillen zijn verwaarloosbaar voor de meeste applicaties. Beide bibliotheken gebruiken onder de motorkap het reactiviteitssysteem van Vue. De praktische performancewinst komt voort uit verminderde boilerplate die leidt tot minder re-renders veroorzaakt door te brede state-subscriptions — het platte store-model van Pinia stimuleert granulaire stores, wat betekent dat componenten minder state abonneren. Met de introductie van [Vapor Mode](https://vuejs.org/guide/extras/reactivity-in-depth.html) in Vue 3.6 profiteren zowel Pinia als Vuex van de snellere rendering-pipeline. Pinia is echter door de nauwere integratie met de Composition API beter gepositioneerd voor Vapor Mode-optimalisaties. ## Veelgestelde Vue State Management Sollicitatievragen Technische sollicitatiegesprekken testen regelmatig kennis over state management. Hier volgen de vragen die in 2026 het vaakst worden gesteld in Vue-ontwikkelaarsgesprekken. **V: Waarom is de mutation-laag van Vuex verwijderd in Pinia?** Mutations bestonden in Vuex om time-travel debugging in DevTools mogelijk te maken. Elke state-wijziging moest via een synchrone mutation verlopen zodat DevTools snapshots konden vastleggen. Pinia bereikt dezelfde debugging-mogelijkheid door state-wijzigingen op reactief niveau te tracken, waardoor de expliciete mutation-laag overbodig wordt. Het resultaat: minder boilerplate, dezelfde debugging-kracht. **V: Wanneer verdient een Setup store de voorkeur boven een Options store?** Setup stores zijn de betere keuze wanneer de store composables nodig heeft (`useRoute`, `useDebounceFn`), complexe watchers, of gedeelde logica uit externe composable-functies. Options stores werken goed voor eenvoudige CRUD-state met basale getters. In de praktijk komen Setup stores vaker voor in productie-codebases omdat ze de Composition API-patronen in componenten weerspiegelen. **V: Hoe behandelt Pinia reactiviteit voor geneste objecten?** Pinia gebruikt Vue's `reactive()` voor het gehele state-object en `ref()` voor individuele eigenschappen in Setup stores. Diepe reactiviteit geldt standaard — mutaties van geneste objecten worden automatisch getrackt. Voor performance-gevoelige gevallen met grote datasets kan `shallowRef()` diepe reactiviteit uitschakelen. **V: Leg store-tot-store afhankelijkheden uit in Pinia vs Vuex.** In Vuex maakt cross-module toegang gebruik van `rootState`- en `rootGetters`-parameters in actions, wat impliciete koppeling creëert. In Pinia importeren stores elkaar direct via `useOtherStore()`-aanroepen. Dit maakt afhankelijkheden expliciet en stelt TypeScript in staat deze tijdens compilatie te verifiëren. Circulaire afhankelijkheden werken in Pinia zolang ze niet worden aangeroepen tijdens de initiële setup-fase. **V: Wat gebeurt er met Pinia-state tijdens SSR-hydration?** Tijdens SSR serialiseert Pinia alle actieve store-states naar JSON en sluit het resultaat in de HTML-payload in. Op de client hydrateert Pinia elke store voordat componenten worden gemount. Elke state die tijdens server-side rendering is ingesteld, is direct beschikbaar op de client zonder dubbele API-aanroepen. In Nuxt 4 is dit proces volledig automatisch. Voor meer Vue- en Nuxt-sollicitatievoorbereiding zijn het [state management interviewmodule](/technologies/vue-nuxt/interview-questions/nuxt-state-management) en het [Vue composables module](/technologies/vue-nuxt/interview-questions/vue-composables) beschikbaar. ## Conclusie - Pinia 3 is de officiële Vue state management bibliotheek — Vuex bevindt zich in onderhoudsmodus zonder geplande v5-release - De mutation-laag is verdwenen: Pinia actions wijzigen state direct, wat boilerplate met ~40% vermindert - TypeScript-inferentie werkt direct uit de doos in Pinia zonder augmentation, in tegenstelling tot de handmatige type-declaraties van Vuex - Setup stores integreren naadloos met de Vue 3 Composition API, wat hergebruik van composables en watchers binnen stores mogelijk maakt - Platte store-architectuur vervangt de geneste module-boom van Vuex, waardoor communicatie tussen stores expliciet en type-safe wordt - Migratie kan incrementeel plaatsvinden: Pinia en Vuex bestaan naast elkaar, wat module-voor-module conversie mogelijk maakt - SSR-hydration is automatisch in Nuxt 4 met Pinia — geen handmatige serialisatie nodig - Voor alle nieuwe Vue 3-projecten in 2026 is Pinia de duidelijke keuze met een betere developer experience, kleinere bundels en sterkere ecosysteemondersteuning --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/nl/blog/vue-nuxt/vue-3-pinia-vs-vuex-state-management