# NgRx Signal Store vs Klasik NgRx 2026: Hangisini Secmelisiniz? > Angular durum yonetimi icin NgRx Signal Store ve Klasik NgRx kapsamli karsilastirmasi. Pratik kod ornekleri ve 2026 tavsiyeleri. - Published: 2026-07-11 - Updated: 2026-07-11 - Author: SharpSkill - Tags: angular, ngrx, state-management, signals, typescript - Reading time: 9 min --- NgRx Signal Store, geleneksel Redux tabanli aksiyonlar-reducer'lar-selectorlar kalibini sinyal tabanli reaktif bir yaklasimla degistirerek Angular durum yonetiminde temel bir degisimi temsil etmektedir. Bu karsilastirma, Angular gelistiricilerinin 2026 yilinda bilinçli mimari kararlar vermelerine yardimci olmak için her iki çözümü incelemektedir. > **Hizli Karar Rehberi** > > Boilerplate azaltmanin önemli oldugu özellik düzeyinde durum ve orta karmasiklikta uygulamalar için **Signal Store** kullanilmalidir. Siki denetim izleri, karmasik yan etkiler ve kapsamli DevTools hata ayiklamasi gerektiren kurumsal uygulamalar için **Klasik NgRx** kullanilmalidir. ## Mimari Farkliliklari Anlama Klasik NgRx, [Redux kalibi](https://redux.js.org/understanding/thinking-in-redux/three-principles) üzerine kuruludur: aksiyonlar olaylari tanimlar, reducer'lar yeni degismez durum üretir ve selectorlar verileri çikarir. Her durum degisikligi öngörülebilir, izlenebilir bir boru hattindan geçer. Signal Store farkli bir yaklasim benimser. Aksiyonlari reducer'lar araciligiyla göndermek yerine, durum reaktif sinyallerde yasir. Güncellemeler `patchState()` çagiran metodlar araciligiyla gerçeklesir ve türetilmis degerler memoize edilmis selectorlar yerine computed signal'lardan gelir. | Yön | Klasik NgRx | Signal Store | |-----|-------------|---------------| | Zihinsel Model | Redux/Flux | Reaktif Servisler | | Boilerplate | Yüksek (aksiyonlar, reducer'lar, selectorlar, efektler) | Düsük (durum, metodlar, computed) | | Reaktivite | RxJS Observable'lar | Angular Signal'lar | | DevTools | Tam Redux DevTools | Signal Store DevTools (eklenti ile) | | Ögrenme Egrisi | Dik | Orta | | Bundle Boyutu | Daha Büyük | Daha Küçük | Angular Signals'a zaten asina olan gelistiriciler için Signal Store, framework'ün reaktif ilkellerinin dogal bir uzantisi gibi hissedilir. ## Klasik NgRx: Angular'da Redux Kalibi Klasik NgRx, durum yönetimini aksiyonlar, reducer'lar, selectorlar ve efektler etrafinda organize eder. Bu ayrim, uzunluk pahesina öngörülebilirligi zorlar. ```typescript // books.actions.ts import { createActionGroup, emptyProps, props } from '@ngrx/store'; import { Book } from './book.model'; export const BooksActions = createActionGroup({ source: 'Books', events: { 'Load Books': emptyProps(), 'Load Books Success': props<{ books: Book[] }>(), 'Load Books Failure': props<{ error: string }>(), 'Add Book': props<{ book: Book }>(), 'Remove Book': props<{ id: string }>(), }, }); ``` `createActionGroup` API'si ilgili aksiyonlari tek bir kaynak altinda gruplar, DevTools okunabilirligini artir ve ayri `createAction` çagrilarina kiyasla boilerplate'i azaltir. ```typescript // books.reducer.ts import { createReducer, on } from '@ngrx/store'; import { BooksActions } from './books.actions'; import { Book } from './book.model'; export interface BooksState { books: Book[]; loading: boolean; error: string | null; } const initialState: BooksState = { books: [], loading: false, error: null, }; export const booksReducer = createReducer( initialState, on(BooksActions.loadBooks, (state) => ({ ...state, loading: true, error: null, })), on(BooksActions.loadBooksSuccess, (state, { books }) => ({ ...state, books, loading: false, })), on(BooksActions.loadBooksFailure, (state, { error }) => ({ ...state, loading: false, error, })) ); ``` Reducer'lar yeni durum nesneleri döndüren saf fonksiyonlar olarak kalir. `on()` fonksiyonu aksiyon eslestirmeyi ve durum güncellemelerini özlü bir sekilde yönetir. ```typescript // books.selectors.ts import { createFeatureSelector, createSelector } from '@ngrx/store'; import { BooksState } from './books.reducer'; export const selectBooksState = createFeatureSelector('books'); export const selectAllBooks = createSelector( selectBooksState, (state) => state.books ); export const selectBooksLoading = createSelector( selectBooksState, (state) => state.loading ); export const selectPublishedBooks = createSelector( selectAllBooks, (books) => books.filter((book) => book.published) ); ``` Selectorlar otomatik olarak memoizasyon saglar. `selectPublishedBooks` selectoru sadece kitaplar dizisi degistiginde yeniden hesaplanir, bu da sik güncellenen store'larda bile okumalari verimli kilar. ## NgRx Signal Store: Sinyal Öncelikli Durum Yönetimi Signal Store, durumu, computed degerleri ve metodlari tek bir enjekte edilebilir servis içinde birlestirir. [Resmi NgRx dokümantasyonu](https://ngrx.io/guide/signals/signal-store) bunu "Angular Signals için yerel destekli, tam özellikli bir durum yönetimi çözümü" olarak tanimlar. ```typescript // books.store.ts import { computed, inject } from '@angular/core'; import { patchState, signalStore, withComputed, withMethods, withState } from '@ngrx/signals'; import { BooksService } from './books.service'; import { Book } from './book.model'; interface BooksState { books: Book[]; loading: boolean; error: string | null; } const initialState: BooksState = { books: [], loading: false, error: null, }; export const BooksStore = signalStore( { providedIn: 'root' }, withState(initialState), withComputed(({ books }) => ({ publishedBooks: computed(() => books().filter((book) => book.published)), totalBooks: computed(() => books().length), })), withMethods((store, booksService = inject(BooksService)) => ({ async loadBooks() { patchState(store, { loading: true, error: null }); try { const books = await booksService.getAll(); patchState(store, { books, loading: false }); } catch (error) { patchState(store, { loading: false, error: 'Failed to load books' }); } }, addBook(book: Book) { patchState(store, ({ books }) => ({ books: [...books, book] })); }, removeBook(id: string) { patchState(store, ({ books }) => ({ books: books.filter((book) => book.id !== id), })); }, })) ); ``` Tüm özelligin durum yönetimi tek bir dosyaya sigar. Durum özellikleri otomatik olarak sinyal olur, computed signal'lar selectorlarin yerini alir ve metodlar aksiyon gönderimlerinin yerini alir. ## withEntities ile Varlık Yönetimi Her iki yaklasim da varlik koleksiyonlarini destekler, ancak Signal Store'un `withEntities` özelligi kodu önemli ölçüde azaltir. ```typescript // books-entity.store.ts import { computed, inject } from '@angular/core'; import { patchState, signalStore, withComputed, withMethods } from '@ngrx/signals'; import { addEntity, removeEntity, setAllEntities, updateEntity, withEntities, } from '@ngrx/signals/entities'; import { BooksService } from './books.service'; import { Book } from './book.model'; export const BooksEntityStore = signalStore( { providedIn: 'root' }, withEntities(), withComputed(({ entities }) => ({ publishedBooks: computed(() => entities().filter((book) => book.published)), })), withMethods((store, booksService = inject(BooksService)) => ({ async loadBooks() { const books = await booksService.getAll(); patchState(store, setAllEntities(books)); }, addBook(book: Book) { patchState(store, addEntity(book)); }, updateBook(id: string, changes: Partial) { patchState(store, updateEntity({ id, changes })); }, removeBook(id: string) { patchState(store, removeEntity(id)); }, })) ); ``` `withEntities` özelligi otomatik olarak `ids`, `entityMap` ve `entities` sinyallerini saglar. `addEntity`, `removeEntity` ve `updateEntity` gibi varlık güncelleyicileri koleksiyon mutasyonlarini yönetir. ## Yeniden Kullanilabilirlik için Özel Store Özellikleri Signal Store'un `signalStoreFeature` fonksiyonu, kesisen ilgi alanlarinin çikartilmasini ve farkli store'larda yeniden kullanilmasini saglar. ```typescript // with-request-status.ts import { computed } from '@angular/core'; import { signalStoreFeature, withComputed, withState } from '@ngrx/signals'; type RequestStatus = 'idle' | 'pending' | 'fulfilled' | 'error'; export function withRequestStatus() { return signalStoreFeature( withState<{ requestStatus: RequestStatus }>({ requestStatus: 'idle' }), withComputed(({ requestStatus }) => ({ isPending: computed(() => requestStatus() === 'pending'), isFulfilled: computed(() => requestStatus() === 'fulfilled'), isError: computed(() => requestStatus() === 'error'), })) ); } export function setPending(): { requestStatus: RequestStatus } { return { requestStatus: 'pending' }; } export function setFulfilled(): { requestStatus: RequestStatus } { return { requestStatus: 'fulfilled' }; } export function setError(): { requestStatus: RequestStatus } { return { requestStatus: 'error' }; } ``` Bu özel özellik artik yükleme durumu izlemesi gerektiren herhangi bir store'a eklenebilir. ```typescript // books-with-status.store.ts import { inject } from '@angular/core'; import { patchState, signalStore, withMethods } from '@ngrx/signals'; import { setAllEntities, withEntities } from '@ngrx/signals/entities'; import { withRequestStatus, setFulfilled, setPending, setError } from './with-request-status'; import { BooksService } from './books.service'; import { Book } from './book.model'; export const BooksStore = signalStore( { providedIn: 'root' }, withEntities(), withRequestStatus(), withMethods((store, booksService = inject(BooksService)) => ({ async loadBooks() { patchState(store, setPending()); try { const books = await booksService.getAll(); patchState(store, setAllEntities(books), setFulfilled()); } catch { patchState(store, setError()); } }, })) ); ``` Birlesmis store artik mantigi çogaltmadan `isPending()`, `isFulfilled()` ve `isError()` computed signal'larini açiga çikarir. ## Bilesken Entegrasyon Kaliplari Signal Store, sinyal okumalari araciligiyla Angular'in sablon sözdizimi ile dogal olarak bütünlesir. ```typescript // books-list.component.ts import { Component, inject } from '@angular/core'; import { BooksStore } from './books.store'; @Component({ selector: 'app-books-list', standalone: true, template: ` @if (store.isPending()) {
Kitaplar yükleniyor...
} @if (store.isError()) {
Kitaplar yüklenemedi
} @for (book of store.entities(); track book.id) {

{{ book.title }}

{{ book.author }}

}

Toplam: {{ store.totalBooks() }} kitap

`, }) export class BooksListComponent { readonly store = inject(BooksStore); constructor() { this.store.loadBooks(); } } ``` Abonelik yönetimi yok. Async pipe'lar yok. Sinyaller, optimum performans için Angular'in zoneless degisiklik algilimasiyla bütünlesir. ## Performans ve Bundle Boyutu Degerlendirmeleri Signal Store'un daha hafif mimarisi daha küçük bundle'lara dönüsür. Çekirdek `@ngrx/signals` paketi yaklasik 4KB gzip eklerken, tam klasik NgRx yigini (`@ngrx/store`, `@ngrx/effects`, `@ngrx/entity`) 15-20KB ekler. Signal Store ayrica Angular'in sinyal tabanli degisiklik algilamasindan da yararlanir. Computed signal'lar yalnizca bagimliliklar degistiginde yeniden hesaplanir ve bilesenler yalnizca tüketilen sinyaller güncellendiginde yeniden render edilir. Bu granüler reaktivite, Observable tabanli kaliplarda yaygin olan gereksiz degisiklik algilama döngülerini ortadan kaldirir. Halihazirda yogun RxJS kullanan uygulamalar için, klasik NgRx'in Observable tabanli selectorlari mevcut boru hatlariyla sorunsuzca bütünlesir. ## Klasikten Signal Store'a Migrasyon Stratejisi Mevcut bir klasik NgRx uygulamasini tasinak büyük bir yeniden yazip gerektirmez. Her iki çözüm bir arada var olabilir ve kademeli benimsemeyi mümkün kilar. - Signal Store kullanarak yeni özelliklerle baslamak - Izole özellik modüllerini birer birer tasinak - Migrasyon maliyeti faydasini asarsa, karmasik, efekt agirlikli özellikleri klasik NgRx'te tutmak - Observable tabanli ve sinyal tabanli durum arasinda köprü kurmak için [NgRx Signals interop](https://ngrx.io/guide/signals) yardimci programlarini kullanmak > **Birlikte Varlik Çalisiyor** > > Klasik NgRx Store ve Signal Store ayni uygulamada yan yana çalisabilir. NgRx ekibi her iki yaklasimi da resmi olarak destekler ve aralarinda köprü kurmak için interop yardimci programlari saglar. ## Her Yaklasimi Ne Zaman Seçmeli ### Signal Store'u su durumlarda seçin: - Yeni Angular 20+ uygulamalari olusturma - Özellik düzeyinde veya bilesen düzeyinde durum yönetimi - Gelistirici deneyimi ve azaltilmis boilerplate önceliklendirme - Ekibin sinirli NgRx deneyimi var - Bundle boyutu önemli ### Klasik NgRx'i su durumlarda seçin: - Mevcut NgRx uygulamalarinin bakami - Siki aksiyon günlükleme ve denetim izleri gereksinimi - Kapsamli yan etkilerle karmasik is akislari olusturma - Tam Redux DevTools zaman yolculugu hata ayiklamasi gereksinimi - Ekibin derin NgRx uzmanligi var Her iki yaklasimda da durum yönetimi temellerini anlamak, gelistiricileri çesitli Angular kod tabanlarina hazirlar. ## Sonuç - Signal Store, klasik NgRx'e kiyasla durum yönetimi boilerplate'ini %60-70 azaltir - Klasik NgRx, siki denetim izleri ve karmasik yan etkiler gerektiren kurumsal uygulamalar için daha iyi seçim olmaya devam eder - Her iki yaklasim ayni uygulamada bir arada var olabilir ve kademeli migrasyonu mümkün kilar - Signal Store'un computed signal'lari açik selector tanimlari olmadan otomatik memoizasyon saglar - Özel store özellikleri (`signalStoreFeature`) yeniden kullanilabilir kesisen ilgi alanlari saglar - 2026'da yeni Angular 20+ projeleri için, belirli gereksinimler klasik NgRx'i gerektirmedikçe Signal Store varsayilan seçim olmalidir --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/tr/blog/angular/ngrx-signal-store-vs-classic-ngrx-comparison