Vue 3 Pinia vs Vuex: Modern Durum Yönetimi ve Mülakat Soruları 2026

Pinia ve Vuex karşılaştırması: API tasarımı, TypeScript, Composition API entegrasyonu, performans, geçiş yolu ve 2026 Vue mülakat soruları.

Vue 3 Pinia ve Vuex durum yönetimi karşılaştırması ve kod örnekleri

Pinia ve Vuex karşılaştırması, Vue 3'ün piyasaya sürülmesinden bu yana Vue durum yönetimindeki en önemli değişimi temsil etmektedir. Pinia 3 artık resmi öneri olarak kabul edilirken, Vuex bakım moduna alınmış durumda. Bu iki kütüphane arasındaki farkları anlamak, Vue geliştiricileri için zorunlu bir bilgi haline gelmiş ve 2026 yılında teknik mülakatlarda sıkça karşılaşılan bir konu olmaya devam etmektedir.

Temel Bilgi

Pinia, Vue 3 için resmi durum yönetimi çözümüdür. Vuex 5 iptal edilmiş ve Evan You, Pinia'yı fiili Vuex 5 olarak tanımlamıştır. Tüm yeni Vue 3 projeleri Pinia 3 kullanmalıdır.

Pinia vs Vuex: Temel Mimari Farklar

Pinia ile Vuex arasındaki temel mimari fark, durum mutasyonlarının nasıl gerçekleştiğinde yatmaktadır. Vuex, katı bir tek yönlü veri akışı uygular: bileşenler aksiyonları dispatch eder, aksiyonlar mutasyonları commit eder ve mutasyonlar durumu değiştirir. Pinia ise mutasyon katmanını tamamen ortadan kaldırarak aksiyonlardan ve hatta bileşenlerden doğrudan durum değişikliğine izin verir.

Bu sadeleştirme, çoğu kod tabanında boilerplate'i yaklaşık %40 oranında azaltır. Vuex dört kavram gerektirirken (state, getters, mutations, actions), Pinia üç kavramla çalışır (state, getters, actions).

| Özellik | Pinia 3 | Vuex 4 | |---------|---------|--------| | Mutasyonlar | Yok (doğrudan durum değişiklikleri) | Durum değişiklikleri için zorunlu | | TypeScript | Tam tip çıkarımı, augmentasyon gereksiz | Manuel tip augmentasyonu gerekli | | Store mimarisi | Birden fazla düz store | Tek store, iç içe modüller | | Composition API | Doğal destek | Options API tabanlı | | Bundle boyutu | ~1 KB gzipped | ~6 KB gzipped | | Vue Devtools | Tam destek (v7) | Tam destek | | SSR | Yerleşik | Yapılandırma gerektirir | | Hot Module Replacement | Yerleşik | Manuel kurulum |

Store Tanımlama: Options API vs Setup Söz Dizimi

Pinia, store tanımlamak için iki söz dizimi sunar. Options söz dizimi, Vuex'in yapısını yansıtarak geçişi kolaylaştırır. Setup söz dizimi, maksimum esneklik için Vue 3'ün Composition API'sinden yararlanır.

stores/counter-options.tstypescript
import { defineStore } from 'pinia'

// Options Store syntax — familiar to Vuex developers
export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
    lastUpdated: null as Date | null,
  }),
  getters: {
    // Getters receive state as first argument with full type inference
    doubleCount: (state) => state.count * 2,
    isPositive(): boolean {
      // Access other getters via `this`
      return this.count > 0
    },
  },
  actions: {
    increment() {
      // Direct state mutation — no commit() needed
      this.count++
      this.lastUpdated = new Date()
    },
    async fetchCount(id: string) {
      // Async actions work without extra configuration
      const response = await fetch(`/api/counters/${id}`)
      const data = await response.json()
      this.count = data.count
    },
  },
})

Options söz dizimi, Vuex kavramlarından doğrudan bir eşleme sağlar. State, Vuex'teki state'in yerini alır; getter'lar getter olarak kalır ve aksiyonlar hem Vuex aksiyonlarını hem de mutasyonlarını bünyesinde barındırır.

stores/counter-setup.tstypescript
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

// Setup Store syntax — identical patterns to Composition API
export const useCounterStore = defineStore('counter', () => {
  // ref() becomes state
  const count = ref(0)
  const lastUpdated = ref<Date | null>(null)

  // computed() becomes getters
  const doubleCount = computed(() => count.value * 2)
  const isPositive = computed(() => count.value > 0)

  // Functions become 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
  }

  // Must return all state, getters, and actions
  return { count, lastUpdated, doubleCount, isPositive, increment, fetchCount }
})

Setup söz dizimi tam esneklik sağlar: watcher'lar, composable yeniden kullanımı ve koşullu mantık, store tanımı içinde doğal olarak çalışır. Karşılığında, her reaktif özellik ve metodun açıkça döndürülmesi gerekmektedir.

TypeScript Entegrasyonu: Pinia'nın Vuex'i Geride Bıraktığı Nokta

TypeScript desteği, Pinia'nın kesin olarak üstünlük sağladığı alandır. Vuex 4, modül bildirimleri aracılığıyla manuel tip augmentasyonu gerektir ve karmaşık iç içe modüller tip çıkarımını kırılgan hale getirir. Pinia, store tanımından tipleri otomatik olarak çıkarır.

typescript
// Vuex 4 — manual type augmentation required
import { Store } from 'vuex'

declare module 'vuex' {
  interface State {
    counter: {
      count: number
      lastUpdated: Date | null
    }
  }
}

// Accessing state requires type assertions or custom helpers
const count = (store.state as { counter: { count: number } }).counter.count
typescript
// Pinia — full type inference, zero configuration
const counter = useCounterStore()

// TypeScript knows counter.count is number
// TypeScript knows counter.doubleCount is number
// TypeScript knows counter.increment() returns void
// TypeScript knows counter.fetchCount() returns Promise<void>
counter.increment()
console.log(counter.doubleCount)

Pinia ayrıca yeniden kullanılabilir kalıplar için generic store'ları da destekler — Vuex'te önemli miktarda boilerplate gerektiren bir yetenek.

Composition API ve Composable Entegrasyonu

Pinia'nın Setup store'ları herhangi bir Vue composable'ını kabul eder ve bu sayede paylaşılan VueUse yardımcıları veya router farkındalığına sahip durum gibi güçlü kalıpları mümkün kılar.

stores/search.tstypescript
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<SearchResult[]>([])
  const isLoading = ref(false)

  // VueUse composable used directly inside the store
  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 syncs URL query param to 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 }
})

Bu kalıp, geçici çözümler olmadan Vuex'te uygulanamaz. Vuex modülleri, tanımları içinde composable'lar, watcher'lar veya router hook'ları kullanamazlar. Store mantığının Vuex modülü ile harici yardımcı fonksiyonlar arasında bölünmesi gerekir.

Vue.js / Nuxt.js mülakatlarında başarılı olmaya hazır mısın?

İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.

Store'lar Arası İletişim ve Çapraz Referanslar

Vuex, namespace'li modüllere sahip tek bir kök store kullanır. Modüller arasında duruma erişim, ayrıntılı rootState ve rootGetters parametreleri gerektirir. Pinia store'ları tasarım gereği bağımsızdır ve store'lar arası iletişim doğrudan import'larla sağlanır.

stores/cart.tstypescript
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<CartItem[]>([])

  const total = computed(() => {
    // Access another store by calling its 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('Authentication required')
    }
    // Checkout logic
  }

  return { items, total, checkout }
})

Düz store mimarisi, büyük Vuex uygulamalarını gezinmesi ve yeniden yapılandırması zor hale getiren derin iç içe modül ağaçlarını ortadan kaldırır.

Vuex 4'ten Pinia 3'e Geçiş

Vuex'ten Pinia'ya geçiş, modül modül gerçekleştirilebilir. Her iki kütüphane de geçiş süreci boyunca bir arada var olabilir. Önerilen strateji: yaprak modüllerden (başka hiçbir modülün bağımlı olmadığı store'lar) başlamak ve merkeze doğru ilerlemektir.

Geçiş Uyumluluğu

Pinia ve Vuex aynı uygulamada yan yana çalışabilir. Pinia'yı Vuex'in yanına kurmak, her seferinde bir modül taşımak ve tüm modüller dönüştürüldükten sonra Vuex'i kaldırmak yeterlidir.

typescript
// Before: 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<UserPreferences>) {
      state.preferences = { ...state.preferences, ...prefs }
    },
  },
  actions: {
    async fetchProfile({ commit }) {
      const profile = await api.getProfile()
      commit('SET_PROFILE', profile)
    },
    async updatePreferences({ commit }, prefs: Partial<UserPreferences>) {
      await api.updatePreferences(prefs)
      commit('UPDATE_PREFERENCES', prefs)
    },
  },
  getters: {
    isLoggedIn: (state) => state.profile !== null,
    displayName: (state) => state.profile?.name ?? 'Guest',
  },
}
typescript
// After: 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<UserProfile | null>(null)
  const preferences = ref<UserPreferences>({})

  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<UserPreferences>) {
    await api.updatePreferences(prefs)
    Object.assign(preferences.value, prefs)
  }

  return { profile, preferences, isLoggedIn, displayName, fetchProfile, updatePreferences }
})

Geçiş kalıbı tutarlıdır: mutasyonlar, aksiyonlar içindeki doğrudan atamalara dönüşür; commit() çağrıları ortadan kalkar ve mapState/mapGetters yardımcıları, store composable'ının destrukturasyonuyla değiştirilir.

Pinia ve Nuxt 4 ile SSR Durum Hidratasyonu

Sunucu tarafı render (SSR), durum yönetimine karmaşıklık getirir. Pinia, Nuxt 4 içinde SSR durum serileştirmesini ve hidratasyonunu otomatik olarak yönetirken, Vuex manuel window.__INITIAL_STATE__ işlenmesini gerektirir.

SSR Tuzağı

useRoute() veya useFetch() gibi composable'lar kullanan Setup store'ları, SSR bağlamında dikkatli kullanım gerektirir. Bu composable'lar yalnızca setup aşamasında çağrılmalı, asenkron callback'ler içinde asla çağrılmamalıdır.

stores/products.ts — SSR-safe Pinia store for Nuxt 4typescript
import { defineStore } from 'pinia'

export const useProductStore = defineStore('products', {
  state: () => ({
    items: [] as Product[],
    selectedCategory: 'all',
  }),
  actions: {
    async fetchProducts() {
      // useFetch is Nuxt-specific — use $fetch for store actions
      this.items = await $fetch<Product[]>('/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, Pinia durumunu sunucuda otomatik olarak serileştirir ve istemcide hidratasyon gerçekleştirir. Manuel replaceState() veya dehidrasyon mantığı gerekmez.

Performans Karşılaştırması ve Bundle Etkisi

Pinia'nın gzip sonrası ~1 KB'lık boyutu, Vuex'in ~6 KB'lık boyutunun yaklaşık 6 katı daha küçüktür. Code splitting kullanan uygulamalarda Pinia store'ları tree-shaking'e tabidir: kullanılmayan store'lar ve bağımlılıkları üretim bundle'larından çıkarılır.

Çalışma zamanı performans farkları çoğu uygulama için ihmal edilebilir düzeydedir. Her iki kütüphane de altta Vue'nun reaktivite sistemini kullanır. Pratik performans kazancı, daha az boilerplate'in daha az yeniden render'a yol açmasından kaynaklanır — Pinia'nın düz store modeli granüler store'lar oluşturmayı teşvik eder, bu da bileşenlerin daha az duruma abone olması anlamına gelir.

Vue 3.6'nın Vapor Mode tanıtımıyla birlikte hem Pinia hem de Vuex daha hızlı render pipeline'ından faydalanır. Ancak Pinia'nın Composition API ile daha sıkı entegrasyonu, Vapor Mode optimizasyonları için daha iyi konumlanmasını sağlar.

Sık Sorulan Vue Durum Yönetimi Mülakat Soruları

Teknik mülakatlar, durum yönetimi bilgisini düzenli olarak test eder. 2026 yılında Vue geliştirici mülakatlarında en sık karşılaşılan sorular aşağıda yer almaktadır.

S: Vuex'in mutasyon katmanı neden Pinia'da kaldırıldı?

Mutasyonlar, DevTools'ta zaman yolculuğu (time-travel) hata ayıklamasını mümkün kılmak için Vuex'te bulunuyordu. Her durum değişikliğinin senkron bir mutasyondan geçmesi gerekiyordu, böylece DevTools anlık görüntüler kaydedebiliyordu. Pinia, durum değişikliklerini reaktivite düzeyinde takip ederek aynı hata ayıklama yeteneğini sağlar ve açık mutasyon katmanını gereksiz kılar. Sonuç: daha az boilerplate, aynı hata ayıklama gücü.

S: Setup store ne zaman Options store'a tercih edilmelidir?

Setup store'lar, store'un composable'lara (useRoute, useDebounceFn), karmaşık watcher'lara veya harici composable fonksiyonlarından paylaşılan mantığa ihtiyaç duyduğu durumlarda daha iyi bir tercihtir. Options store'lar, basit getter'lara sahip doğrudan CRUD durumları için iyi çalışır. Pratikte Setup store'lar, bileşen Composition API kalıplarını yansıttıkları için üretim kod tabanlarında daha yaygındır.

S: Pinia, iç içe nesneler için reaktiviteyi nasıl yönetir?

Pinia, tüm durum nesnesi için Vue'nun reactive() fonksiyonunu ve Setup store'larda bireysel özellikler için ref() fonksiyonunu kullanır. Derin reaktivite varsayılan olarak uygulanır — iç içe nesne mutasyonları otomatik olarak takip edilir. Büyük veri setleriyle performansa duyarlı durumlarda, shallowRef() derin reaktiviteden çıkmayı sağlar.

S: Pinia'da store'lar arası bağımlılıklar Vuex ile nasıl karşılaştırılır?

Vuex'te modüller arası erişim, aksiyonlardaki rootState ve rootGetters parametrelerini kullanarak örtük bağlantılar oluşturur. Pinia'da store'lar birbirlerini useOtherStore() çağrıları aracılığıyla doğrudan import eder. Bu, bağımlılıkları açık hale getirir ve TypeScript'in bunları derleme zamanında doğrulamasını sağlar. Döngüsel bağımlılıklar, başlangıç setup aşamasında çağrılmadıkları sürece Pinia'da çalışır.

S: SSR hidratasyonu sırasında Pinia durumuna ne olur?

SSR sırasında Pinia, tüm aktif store durumlarını JSON'a serileştirir ve sonucu HTML payload'una gömer. İstemcide Pinia, bileşenler mount edilmeden önce her store'u hidratasyon ile doldurur. Sunucu tarafı render sırasında ayarlanan durum, mükerrer API çağrıları olmadan istemcide hemen kullanılabilir. Nuxt 4'te bu süreç tamamen otomatiktir.

Daha fazla Vue ve Nuxt mülakat hazırlığı için durum yönetimi mülakat modülü veya Vue composable'lar modülü incelenebilir.

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

Sonuç

  • Pinia 3, Vue'nun resmi durum yönetimi kütüphanesidir — Vuex bakım modunda olup planlanmış bir v5 sürümü bulunmamaktadır
  • Mutasyon katmanı kaldırıldı: Pinia aksiyonları durumu doğrudan değiştirerek boilerplate'i ~%40 oranında azaltır
  • TypeScript tip çıkarımı Pinia'da sıfır augmentasyonla kutudan çıkar çalışır; Vuex'in manuel tip bildirimleri gerekmez
  • Setup store'lar Vue 3 Composition API ile sorunsuz entegre olarak store'lar içinde composable yeniden kullanımı ve watcher'lar sağlar
  • Düz store mimarisi Vuex'in iç içe modül ağacını değiştirir ve store'lar arası iletişimi açık ve tip güvenli hale getirir
  • Geçiş kademeli olarak yapılabilir: Pinia ve Vuex bir arada var olarak modül modül dönüşüm imkanı sunar
  • SSR hidratasyonu Nuxt 4'te Pinia ile otomatiktir — manuel serileştirme gerekmez
  • 2026 yılındaki tüm yeni Vue 3 projeleri için Pinia, daha iyi DX, daha küçük bundle'lar ve daha güçlü ekosistem desteğiyle kesin tercihtir

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

Etiketler

#vue
#pinia
#vuex
#state-management
#typescript

Paylaş

İlgili makaleler