Angular sinyalleri ile durum yönetimi: signal, computed ve effect uygulaması
Beceri rehberi

Angular sinyalleri ile durum yönetimi: signal, computed ve effect uygulaması

Hazırlayan: Mindset Institute EditörlüğüGüncellendi: 5 dk okuma

Angular sinyallerinde signal, computed ve effect kullanımını sepet örneğiyle öğrenin: durum güncelleme, türetilmiş değer ve sık yapılan hatalar.

Sinyal nedir, hangi sorunu çözer?

Sinyal, içinde bir değer tutan ve bu değer değiştiğinde onu okuyan yerleri haberdar eden bir sarmalayıcıdır. Angular, şablonda ya da başka bir sinyalin hesabında okunan sinyali kendisi izler; değer değişince yalnızca etkilenen kısımları günceller. Geliştirici, "bu değişince şunu da güncelle" zincirlerini elle kurmak zorunda kalmaz.

Eski yaklaşımda bileşen alanları düz değişkendi ve ekranın ne zaman yenileneceği değişiklik algılama mekanizmasının genel taramasına bağlıydı. Sinyallerle bağımlılıklar açık hale gelir: hangi hesap hangi değere bağlı, sistem bunu bilir. Sonuç, daha öngörülebilir bir veri akışı ve ince taneli güncellemedir.

signal ile durum oluşturmak ve güncellemek

Resmî belgeye göre yazılabilir bir sinyal signal fonksiyonuyla oluşturulur, başlangıç değeri verilir. Değere erişmek için sinyal bir fonksiyon gibi çağrılır. Değeri değiştirmek için şu yöntemler kullanılır: set yeni değeri doğrudan koyar, update ise önceki değerden yeni değeri hesaplar.

Sepet örneği:

products = signal<Product[]>([]);

ekle(product: Product) { this.products.update(liste => [...liste, product]); }

temizle() { this.products.set([]); }

Şablonda products() yazarak listeyi okursunuz. Dikkat edilecek nokta, güncellemelerin değişmez (immutable) biçimde yapılmasıdır: diziyi yerinde değiştirmek yerine yeni bir dizi üretmek, sinyalin değişimi fark etmesini sağlar. Bir bileşenin dışarıya yalnızca okunabilir hâlini açmak isterseniz asReadonly ile salt okunur görünüm verebilirsiniz.

computed ile türetilmiş değer

Başka sinyallerden hesaplanan değer, ayrı bir alan olarak saklanıp elle senkron tutulmamalıdır. computed bu iş içindir: içindeki sinyaller değiştiğinde değer yeniden hesaplanır, aksi hâlde önceki sonuç korunur. Belgeye göre computed tembel çalışır ve sonucu bellekte tutar; yani okunmadıkça hesaplanmaz.

Sepet örneğine devam:

adet = computed(() => this.products().length); bos = computed(() => !this.adet());

Burada adet, products değişince güncellenir; bos ise adet'e bağlıdır. Böylece sepet boşken "sepetiniz boş" mesajını göstermek için ayrı bir bayrağı güncellemeyi hatırlamanız gerekmez. computed salt okunurdur; içinde set çağırmak ya da yan etki üretmek yanlıştır. Hesaplama saf kalmalı, yani aynı girdilerle aynı sonucu vermelidir.

effect: yan etki için, durum aktarımı için değil

effect, içinde okunan sinyaller değiştiğinde yeniden çalışan bir yan etki tanımlar. Uygun kullanım alanları: günlük kaydı yazmak, tarayıcı depolamasına kopya yazmak, sinyal dışı bir kütüphaneyi (grafik, harita) güncellemek gibi Angular dışındaki dünyayla senkronizasyon.

Örnek: sepet değişince yerel depolamaya yazmak.

constructor() { effect(() => { localStorage.setItem('sepet', JSON.stringify(this.products())); }); }

Sık yapılan hata, effect içinde başka bir sinyali set ederek durum aktarmaktır. Bu, döngü ve karmaşık bağımlılık riski taşır. Bir değer diğerinden türüyorsa computed; kullanıcı girdisine bağlı sıfırlanan bir değer gerekiyorsa linkedSignal tercih edilir. Belgede linkedSignal, başka sinyallere bağlı ama yazılabilen durum olarak tanıtılır. effect içinde okumak istemediğiniz bir sinyal varsa untracked ile bağımlılık oluşturmadan okuyabilirsiniz.

RxJS ve HTTP verisiyle birlikte kullanım

Gerçek uygulamalarda veri sunucudan gelir. HttpClient Observable döndürdüğü için sinyale köprü gerekir. Belgede toSignal, bir Observable'ın son değerini izleyen salt okunur bir sinyal üretir; başlangıç değeri (initialValue) verilebilir ve bileşen yok edilince abonelik otomatik kapanır. Ters yönde toObservable, bir sinyali akışa çevirir; yazım olarak sinyal sakinleştikten sonra değer yayar, yani art arda hızlı güncellemeler tek bir yayına dönüşür.

Pratik bir kural: ekranda okunan senkron durumu sinyalle, zamanlama ve iptal gerektiren işleri (arama, istek) RxJS ile yönetin; ikisi arasında toSignal ve toObservable ile geçiş yapın. Belgede ayrıca resource kavramı async veriyi sinyal tabanlı koda getiren bir özellik olarak anılır; kullanımı ayrı bir kılavuzda yer aldığı için ayrıntı vermeden, sürümünüzün belgesine bakmanız önerilir.

Adım adım geçiş planı ve kontrol listesi

Mevcut bir uygulamayı sinyallere taşırken sırayla ilerleyin:

  • Bileşenin ekranda gösterdiği alanları listeleyin; kullanıcı etkileşimiyle değişenleri signal'e çevirin.
  • Başka alanlardan hesaplanan değerleri computed'a taşıyın; elle güncelleyen kodu silin.
  • Yan etki gerektiren yerleri effect'e ayırın ve her birinde "bu gerçekten yan etki mi" diye sorun.
  • HTTP ve olay akışlarını RxJS'te bırakıp sonucu toSignal ile şablona verin.
  • Servislerde durumu private yazılabilir sinyal olarak tutup dışarıya asReadonly ile açın.

Bu geçiş bir gecede yapılmaz; sinyal ve klasik yaklaşım bir arada çalışabilir. Önce yeni yazılan bileşenlerde başlamak ve test kapsamını koruyarak ilerlemek risk almadan öğrenmenizi sağlar.

Sık yapılan hatalar

Sinyallerde tekrar eden hatalar vardır. Sinyali çağırmayı unutmak sık görülür: şablonda products yerine products() yazılmalıdır; aksi hâlde sinyal nesnesinin kendisi ekrana basılır. Diziyi ya da nesneyi yerinde değiştirmek de yaygındır; değişim fark edilmez ve ekran yenilenmez. Bir başkası, computed içinde yan etki üretmek ya da başka bir sinyali set etmektir; hesaplama saf kalmalıdır.

Bir diğer hata, her küçük değeri effect ile başka bir sinyale kopyalamaktır. Bu, hata ayıklamayı zorlaştıran gizli bağımlılıklar yaratır. Değer başka bir değerden türüyorsa computed, kullanıcı seçimine göre sıfırlanan bir giriş gerekiyorsa linkedSignal kullanın. Son olarak, büyük nesneleri tek bir sinyalde tutup her küçük alan değişiminde tümünü yeniden üretmek yerine, birbirinden bağımsız değişen alanları ayrı sinyallere bölmek hem okunabilirlik hem güncelleme kapsamı açısından daha iyidir.

Mindset programında yeri

Mindset'in Angular ile Kurumsal Web Uygulamaları programında "Durum Yönetimi ve Sinyaller" ayrı bir modül olarak yer alır; mimari, servis katmanı, RxJS, formlar ve performans konularıyla birlikte işlenir. Kurumsal ekran sayısı arttıkça "durumu nerede tutuyoruz" sorusu tutarlı bir yanıt gerektirir; program, bu sorunun sinyal tabanlı cevabını arayüz geliştiren ekipler için bir çerçeveye oturtur. Sürüm farkları nedeniyle uygulamada sürümünüzün resmî belgesine bakmanız önerilir.

İlgili Mindset programı

Angular ile Kurumsal Web Uygulamaları

Sık sorulanlar

Sık sorulan sorular

Sinyaller RxJS yerine mi kullanılır?

Hayır, bunlar birbirini tamamlar. Sinyaller ekranda okunan senkron durum için sade bir model sunar. RxJS ise zamanla ilgili işler, iptal ve olay akışları için güçlüdür. Angular, bu yapılar arasında toSignal ve toObservable ile geçiş sağlar.

computed ile effect arasındaki fark nedir?

computed başka sinyallerden bir değer türetir, salt okunurdur ve yan etki üretmemelidir. effect ise sinyal değişince bir iş yapar, örneğin kayıt yazar ya da dış bir kütüphaneyi günceller. Değer türetmek için effect kullanmak, karmaşıklığı ve hata riskini artırır; bu yüzden önce computed düşünülmelidir.

Dizi veya nesne sinyalini nasıl güncellemeliyim?

Yeni bir dizi ya da nesne üretip update veya set ile verin; örneğin liste.update(eski => [...eski, yeni]) biçiminde. Mevcut diziyi yerinde değiştirmek sinyalin değişimi algılamasını engelleyebilir. Yayılım (spread) sözdizimi ile yeni kopya oluşturmak en yaygın ve okunaklı yoldur.

Sinyal kullanmak için tüm uygulamayı baştan yazmak gerekir mi?

Gerekmez. Sinyaller klasik yapıyla birlikte çalışır. Yeni yazılan bileşenlerde ya da üzerinde çalıştığınız ekranlarda aşamalı olarak kullanmaya başlayabilirsiniz. Sürümünüzün sinyal destekleyip desteklemediğini resmî belgeden kontrol edin ve geçişi, testleri koruyarak küçük parçalar hâlinde yapın.

Servislerde sinyal nasıl kullanılır?

Servis, durumu private bir yazılabilir sinyalde tutar ve dışarıya asReadonly ile salt okunur sürümünü açar. Güncelleme metotları servisin içinde kalır; bileşenler yalnızca okur ve metot çağırır. Bu düzen, durumun tek kaynaktan değişmesini sağlar ve hata ayıklarken değişimin nereden geldiğini bulmayı kolaylaştırır.