Merhaba arkadaşlar, bugün başımı çok ağrıtan bir sorunu ve bu sorunun nasıl beni lifecycle hook'larının derinliklerine gömdüğünü anlatacağım. Vue.js'te component yazarken, özellikle de mounted ve updated hook'larını "şuraya bir şey koyayım, çalışır işte" mantığıyla kullanıyordum. Sonuç? Component'imde kontrol edemediğim, nereden geldiğini anlamadığım side effect'ler ve sonsuz render döngüleri! İşin kötüsü, bu durum özellikle API çağrıları ve DOM manipülasyonu yaparken iyice içinden çıkılmaz bir hal alıyordu.
Karşılaştığım Karmaşa Senaryosu
Bir veri listesi component'im vardı. mounted hook'unda API'den verileri çekiyordum. Sorun yok gibiydi. Ancak, bu listeye filtreleme özelliği eklediğimde işler karıştı. Filtre değiştiğinde listeyi yeniden çekmem gerekiyordu. İlk düşüncem, "Filtre değişti, yani component updated oldu, o halde API çağrısını updated hook'una da koyayım" oldu. Bu hatayı ilk yaptığımda kafayı yemiştim çünkü component sürekli kendini güncelliyor ve sonsuz bir döngüye giriyordu.
Yukarıdaki kodda, updated hook'u herhangi bir data değiştiğinde (hatta belki parent'tan gelen bir prop) çalışacak. Bu da gereksiz yere onlarca API isteğine, performans kaybına ve en kötüsü state tutarsızlığına yol açıyor.
Hook'ları Doğru Anlamak ve Kullanmak
Aslında sorun, hook'ların ne zaman çalıştığını tam anlamamaktan kaynaklanıyor. mounted, component DOM'a eklendiğinde bir kere çalışır. updated ise component'teki herhangi bir reactive data değiştiğinde her seferinde çalışır. Bu yüzden API çağrısı gibi spesifik bir aksiyonu updated içine koymak felakettir.
Benim Kullandığım En Temiz Çözüm: Watchers ve Methods
Çözüm, side effect'leri doğru yere, yani watch özelliğine veya doğrudan bir method çağrısına taşımak. Özellikle belirli bir değişkene (benim durumumda filter) bağlı olan aksiyonlar için watcher kullanmak kesin çözüm.
Bu yapıda, API çağrısı sadece iki yerde tetiklenir: 1) Component ilk yüklendiğinde (mounted), 2) filter değeri bilinçli olarak değiştirildiğinde (watcher). Component'in diğer tüm güncellemelerinde (örneğin başka bir data değişse bile) gereksiz API isteği olmaz. Her şey temiz ve kontrollü!
Özet ve Tavsiyeler
mounted'ı sadece bir kerelik kurulum işleri (event listener ekleme, ilk veri çekme) için kullan.
updated hook'unu, DOM'un güncellenmesinin hemen ardından DOM'a erişmen gereken çok özel durumlar dışında neredeyse hiç kullanma. Onun yerine, belirli bir değerin değişimini izlemek için daima watch kullan.
Side effect'leri mümkün olduğunca methods içinde topla ve onları hook'lardan veya watcher'lardan çağır. Bu, kodu test etmeyi ve anlamayı inanılmaz kolaylaştırır.
Umarım bu deneyimim, sizin de benzer bir karmaşaya düşmenizi engeller. Siz Vue.js'te lifecycle hook'ları ile ilgili benzer zorluklar yaşadınız mı? updated yerine kullandığınız daha farklı, şık pattern'ler var mı? Yorumlarda tartışalım!
Bir veri listesi component'im vardı. mounted hook'unda API'den verileri çekiyordum. Sorun yok gibiydi. Ancak, bu listeye filtreleme özelliği eklediğimde işler karıştı. Filtre değiştiğinde listeyi yeniden çekmem gerekiyordu. İlk düşüncem, "Filtre değişti, yani component updated oldu, o halde API çağrısını updated hook'una da koyayım" oldu. Bu hatayı ilk yaptığımda kafayı yemiştim çünkü component sürekli kendini güncelliyor ve sonsuz bir döngüye giriyordu.
JavaScript:
export default {
data() {
return {
items: [],
filter: ''
};
},
async mounted() {
// İlk veriyi al
this.items = await this.fetchItems(this.filter);
},
async updated() {
// BU ÇOK TEHLİKELİ! Filtre değişince tetiklenir ama başka sebeplerle de tetiklenir!
this.items = await this.fetchItems(this.filter);
},
methods: {
fetchItems(filter) {
// API çağrısı...
}
}
};
Yukarıdaki kodda, updated hook'u herhangi bir data değiştiğinde (hatta belki parent'tan gelen bir prop) çalışacak. Bu da gereksiz yere onlarca API isteğine, performans kaybına ve en kötüsü state tutarsızlığına yol açıyor.
Aslında sorun, hook'ların ne zaman çalıştığını tam anlamamaktan kaynaklanıyor. mounted, component DOM'a eklendiğinde bir kere çalışır. updated ise component'teki herhangi bir reactive data değiştiğinde her seferinde çalışır. Bu yüzden API çağrısı gibi spesifik bir aksiyonu updated içine koymak felakettir.
Çözüm, side effect'leri doğru yere, yani watch özelliğine veya doğrudan bir method çağrısına taşımak. Özellikle belirli bir değişkene (benim durumumda filter) bağlı olan aksiyonlar için watcher kullanmak kesin çözüm.
JavaScript:
export default {
data() {
return {
items: [],
filter: ''
};
},
watch: {
// 'filter' değişkenini izle. Değiştiğinde çalışacak.
filter(newFilter, oldFilter) {
this.loadItems(newFilter);
}
},
async mounted() {
// Sadece ilk yükleme için
await this.loadItems(this.filter);
},
methods: {
async loadItems(filter) {
// API'den verileri çeken merkezi method
this.items = await this.fetchItems(filter);
},
fetchItems(filter) {
// API çağrısı...
}
}
};
Bu yapıda, API çağrısı sadece iki yerde tetiklenir: 1) Component ilk yüklendiğinde (mounted), 2) filter değeri bilinçli olarak değiştirildiğinde (watcher). Component'in diğer tüm güncellemelerinde (örneğin başka bir data değişse bile) gereksiz API isteği olmaz. Her şey temiz ve kontrollü!
mounted'ı sadece bir kerelik kurulum işleri (event listener ekleme, ilk veri çekme) için kullan.
updated hook'unu, DOM'un güncellenmesinin hemen ardından DOM'a erişmen gereken çok özel durumlar dışında neredeyse hiç kullanma. Onun yerine, belirli bir değerin değişimini izlemek için daima watch kullan.
Side effect'leri mümkün olduğunca methods içinde topla ve onları hook'lardan veya watcher'lardan çağır. Bu, kodu test etmeyi ve anlamayı inanılmaz kolaylaştırır.
Umarım bu deneyimim, sizin de benzer bir karmaşaya düşmenizi engeller. Siz Vue.js'te lifecycle hook'ları ile ilgili benzer zorluklar yaşadınız mı? updated yerine kullandığınız daha farklı, şık pattern'ler var mı? Yorumlarda tartışalım!