vue pinia, Vue 3 uygulamalarında paylaşılan state'i (durum) yönetmenin resmi ve günümüzde önerilen yoludur. Birden çok bileşenin aynı veriye eriştiği durumlarda — giriş yapmış kullanıcı, sepet, tema tercihi — bu veriyi tek bir merkezi yerde tutmak istersin. Eskiden bu işin standardı Vuex'ti; ancak Vue ekibi artık yeni projeler için Pinia'yı öneriyor. Bu yazıda Vuex yerine Pinia ile sıfırdan bir store nasıl kurulur, adım adım göreceğiz.
Neden Vuex değil de Pinia?
Pinia, Vuex'in yerini alan resmi state yönetim kütüphanesidir ve birkaç somut sorunu çözdüğü için tercih edilir:
- Daha az tören: Vuex'te değişiklik için
mutationsyazmak zorundaydın. Pinia mutation kavramını tamamen kaldırır; state'i doğrudan ya daactionsiçinden değiştirirsin. - Tam TypeScript desteği: Tipler otomatik çıkarılır;
thisve dönüş değerleri ekstra şablon kodu olmadan tiplenir. - Modüller yok, düz store'lar var: Vuex'in iç içe modül yapısı yerine her store bağımsız bir birimdir. İstediğin store'u istediğin yerden çağırırsın.
- Composition API ile uyumlu: Pinia, Vue 3'ün
setupmantığıyla doğal çalışır ve devtools desteği gelir.
Kısacası Pinia, Vuex'in yaptığı her şeyi daha az kodla ve daha iyi tip güvenliğiyle yapar. Mevcut bir Vuex projen varsa zorla taşımana gerek yok; ama yeni store'ları Pinia ile yazmak mantıklıdır.
Kurulum ve Pinia'yı uygulamaya bağlama
Önce paketi kur, ardından createPinia() ile bir örnek oluşturup uygulamaya tanıt:
npm install pinia
// main.js
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
const app = createApp(App);
app.use(createPinia());
app.mount("#app");
Bu kadar. Artık uygulamanın herhangi bir yerinde store tanımlayıp kullanabilirsin. Vuex'teki tek dev store nesnesi yerine Pinia'da birden fazla küçük store oluşturursun.
İlk store: state, getters ve actions
Bir store, defineStore ile tanımlanır. İlk argüman benzersiz bir kimliktir (devtools bunu kullanır), ikincisi store'un içeriğidir. Aşağıda klasik bir sayaç örneği var:
// stores/counter.js
import { defineStore } from "pinia";
export const useCounterStore = defineStore("counter", {
state: () => ({
count: 0,
name: "Sayaç",
}),
getters: {
double: (state) => state.count * 2,
},
actions: {
increment() {
this.count++;
},
reset() {
this.count = 0;
},
},
});
Üç temel parçayı görüyorsun:
- state: Verinin başlangıç halini döndüren bir fonksiyondur. Fonksiyon olması, her örneğin kendi taze state'ini almasını sağlar.
- getters: State'ten türetilen, hesaplanmış değerlerdir. Vue'nun
computedmantığıyla önbelleğe alınır;doubleburadacountdeğişmedikçe yeniden hesaplanmaz. - actions: State'i değiştiren ve iş mantığını içeren metotlardır. Vuex'in aksine senkron/asenkron ayrımı yoktur; bir action doğrudan
asyncolabilir.
Dikkat edersen Vuex'teki mutations bölümü hiç yok. State'i değiştirmek istediğinde sadece action içinden this.count++ dersin.
Store'u bir bileşende kullanma
Store'u kullanmak için setup içinde çağırırsın. Dönen nesne reaktiftir; şablonda doğrudan kullanabilirsin:
<script setup>
import { useCounterStore } from "@/stores/counter";
const counter = useCounterStore();
</script>
<template>
<p>Sayı: {{ counter.count }}</p>
<p>İki katı: {{ counter.double }}</p>
<button @click="counter.increment()">Artır</button>
<button @click="counter.reset()">Sıfırla</button>
</template>
Burada counter.count, counter.double ve counter.increment() doğrudan erişilebilir. State'i şablonda okuyabilir, action'ı bir tıklamayla çağırabilirsin.
storeToRefs: reaktiviteyi kaybetmeden destructuring
Çoğu zaman store'dan birkaç alanı çıkarıp kısa isimlerle kullanmak istersin. Ama store'u doğrudan destructure edersen reaktivite kaybolur:
// YANLIŞ — count artık reaktif değil
const { count, double } = useCounterStore();
Doğru yol, state ve getter'lar için storeToRefs kullanmaktır. Bu yardımcı, her alanı reaktif bir ref olarak döndürür. Action'lar ise fonksiyon oldukları için doğrudan destructure edilebilir:
import { storeToRefs } from "pinia";
const store = useCounterStore();
const { count, double } = storeToRefs(store); // reaktif kalır
const { increment, reset } = store; // action'lar düz alınır
Asenkron actions ve toplu güncelleme
Gerçek uygulamalarda actions sıklıkla API çağrısı yapar. Vuex'in aksine ayrı bir yapı gerekmez; action'ı async yapman yeterli:
actions: {
async fetchUser(id) {
this.loading = true;
try {
const res = await fetch(`/api/users/${id}`);
this.user = await res.json();
} finally {
this.loading = false;
}
},
}
Birden fazla alanı tek seferde güncellemek istersen $patch kullanabilirsin; bu, tek bir değişiklik olarak izlenir ve devtools'ta daha temiz görünür:
store.$patch({ count: 10, name: "Yeni" });
Ayrıca store.$reset() ile state'i başlangıç değerine döndürebilir, store.$subscribe() ile her değişikliği dinleyebilirsin (örneğin localStorage'a yazmak için). Bunlar Pinia'nın Vuex'e göre günlük işleri ne kadar sadeleştirdiğini gösteren küçük ama değerli ayrıntılardır.
Sık Sorulan Sorular
Pinia mı Vuex mı kullanmalıyım?
Yeni Vue 3 projelerinde Pinia. Vue'nun resmi önerisi artık Pinia'dır ve Vuex bakım moduna alınmıştır. Mevcut büyük bir Vuex projen varsa acil taşıma şart değil, ama yeni özellikleri Pinia ile yazmak ileriye dönük en sağlam seçimdir.
Pinia'da mutations neden yok?
Vuex, devtools'un değişiklikleri izleyebilmesi için mutation'ları zorunlu kılıyordu. Pinia, state değişikliklerini doğrudan izleyebildiği için bu ara katmana gerek kalmadı; state'i action içinde ya da $patch ile değiştirirsin, devtools yine de her adımı kaydeder.
Birden fazla store birbiriyle konuşabilir mi?
Evet. Bir store'un action'ı veya getter'ı içinde başka bir store'u çağırabilirsin: ilgili useOtherStore() fonksiyonunu çağırıp dönen örneği kullanırsın. Vuex'in modül namespace karmaşası olmadan store'lar birbirine erişebilir.
Doğru kurulmuş bir state mimarisi, büyüyen bir Vue uygulamasının bel kemiğidir. Vue 3 + Pinia tabanlı bir proje geliştiriyor veya mevcut Vuex kodunu modernleştirmek istiyorsan benimle iletişime geç — temiz ve ölçeklenebilir bir yapı birlikte kuralım.