# NgRx Signal Store vs NgRx Clássico em 2026: Qual Escolher? > Comparação detalhada entre NgRx Signal Store e NgRx clássico para gerenciamento de estado Angular em 2026. Conheça as diferenças arquiteturais, exemplos de código e dicas para escolher a solução correta. - Published: 2026-07-11 - Updated: 2026-07-11 - Author: SharpSkill - Reading time: 5 min --- NgRx Signal Store representa uma mudança fundamental no gerenciamento de estado do Angular, substituindo o padrão tradicional inspirado no Redux (actions-reducers-selectors) por uma abordagem reativa baseada em signals. Esta comparação examina ambas as soluções para ajudar desenvolvedores Angular a tomar decisões arquiteturais informadas em 2026. > **Guia de Decisão Rápida** > > Usar **Signal Store** para estado em nível de funcionalidade e aplicações de complexidade média onde a redução de boilerplate importa. Usar **NgRx Clássico** para aplicações empresariais que requerem trilhas de auditoria rigorosas, efeitos colaterais complexos e depuração extensiva com DevTools. ## Entendendo as Diferenças Arquiteturais NgRx clássico segue o [padrão Redux](https://redux.js.org/understanding/thinking-in-redux/three-principles): as actions descrevem eventos, os reducers produzem novo estado imutável, e os selectors extraem dados. Cada mudança de estado flui através de um pipeline previsível e rastreável. Signal Store adota uma abordagem diferente. Em vez de despachar actions através de reducers, o estado vive em signals reativos. As atualizações acontecem através de métodos que chamam `patchState()`, e os valores derivados vêm de signals computados em vez de selectors memorizados. | Aspecto | NgRx Clássico | Signal Store | |---------|---------------|---------------| | Modelo Mental | Redux/Flux | Serviços Reativos | | Boilerplate | Alto (actions, reducers, selectors, effects) | Baixo (state, methods, computed) | | Reatividade | Observables RxJS | Signals Angular | | DevTools | Redux DevTools completo | Signal Store DevTools (via plugin) | | Curva de aprendizado | Íngreme | Moderada | | Tamanho do Bundle | Maior | Menor | Para desenvolvedores já familiarizados com [Signals do Angular](/technologies/angular/interview-questions/angular-signals), Signal Store parece uma extensão natural das primitivas reativas do framework. ## NgRx Clássico: O Padrão Redux no Angular NgRx clássico organiza o gerenciamento de estado em torno de actions, reducers, selectors e effects. Essa separação impõe previsibilidade ao custo de verbosidade. ```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 }>(), }, }); ``` A API `createActionGroup` agrupa actions relacionadas sob uma única fonte, melhorando a legibilidade no DevTools e reduzindo o boilerplate comparado com chamadas individuais de `createAction`. ```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, })) ); ``` Os reducers continuam sendo funções puras que retornam novos objetos de estado. A função `on()` lida com a correspondência de actions e atualizações de estado de forma concisa. ```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) ); ``` Os selectors fornecem memorização automaticamente. O selector `selectPublishedBooks` só recalcula quando o array de livros muda, tornando as leituras eficientes mesmo em stores atualizados frequentemente. ## NgRx Signal Store: Gerenciamento de Estado Signals-First Signal Store consolida estado, valores computados e métodos em um único serviço injetável. A [documentação oficial do NgRx](https://ngrx.io/guide/signals/signal-store) o descreve como uma "solução de gerenciamento de estado completamente equipada com suporte nativo para Signals do Angular." ```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), })); }, })) ); ``` Todo o gerenciamento de estado de uma funcionalidade cabe em um único arquivo. As propriedades de estado se tornam signals automaticamente, signals computados substituem selectors, e métodos substituem despachos de actions. ## Gerenciamento de Entidades com withEntities Ambas as abordagens suportam coleções de entidades, mas a funcionalidade `withEntities` do Signal Store reduz drasticamente o código. ```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)); }, })) ); ``` A funcionalidade `withEntities` fornece automaticamente os signals `ids`, `entityMap` e `entities`. Os atualizadores de entidades como `addEntity`, `removeEntity` e `updateEntity` lidam com mutações de coleções. ## Features de Store Personalizadas para Reusabilidade A função `signalStoreFeature` do Signal Store permite extrair e reutilizar preocupações transversais entre stores. ```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' }; } ``` Esta feature personalizada agora pode ser composta em qualquer store que precise de rastreamento do estado de carregamento. ```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()); } }, })) ); ``` O store composto agora expõe os signals computados `isPending()`, `isFulfilled()` e `isError()` sem duplicar lógica. ## Padrões de Integração em Componentes Signal Store se integra naturalmente com a sintaxe de templates do Angular através de leituras de signals. ```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()) {
Carregando livros...
} @if (store.isError()) {
Falha ao carregar livros
} @for (book of store.entities(); track book.id) {

{{ book.title }}

{{ book.author }}

}

Total: {{ store.totalBooks() }} livros

`, }) export class BooksListComponent { readonly store = inject(BooksStore); constructor() { this.store.loadBooks(); } } ``` Sem gerenciamento de subscriptions. Sem pipes async. Os signals se integram com a [detecção de mudanças zoneless](/blog/angular/angular-19-zoneless-change-detection-performance) do Angular para performance otimizada. ## Considerações de Performance e Tamanho de Bundle A arquitetura mais leve do Signal Store se traduz em bundles menores. O pacote core `@ngrx/signals` adiciona aproximadamente 4KB comprimido com gzip, comparado com 15-20KB para o stack completo do NgRx clássico (`@ngrx/store`, `@ngrx/effects`, `@ngrx/entity`). Signal Store também se beneficia da detecção de mudanças baseada em signals do Angular. Signals computados só recalculam quando as dependências mudam, e componentes só re-renderizam quando signals consumidos são atualizados. Esta reatividade granular elimina ciclos desnecessários de detecção de mudanças comuns em padrões baseados em Observables. Para aplicações que já usam [RxJS extensivamente](/blog/angular/rxjs-angular-operators-subjects-signals-interop), os selectors baseados em Observables do NgRx clássico se integram perfeitamente com pipelines existentes. ## Estratégia de Migração de Clássico para Signal Store Migrar uma aplicação NgRx clássica existente não requer uma reescrita completa. Ambas as soluções podem coexistir, permitindo adoção incremental. - Começar com novas funcionalidades usando Signal Store - Migrar módulos de funcionalidades isolados um de cada vez - Manter funcionalidades complexas com muitos effects no NgRx clássico se o custo de migração exceder o benefício - Usar os utilitários de [interoperabilidade do NgRx Signals](https://ngrx.io/guide/signals) para conectar estado baseado em Observables e baseado em signals > **A Coexistência Funciona** > > NgRx Store clássico e Signal Store podem rodar lado a lado na mesma aplicação. O time do NgRx suporta oficialmente ambas as abordagens e fornece utilitários de interoperabilidade para conectá-las. ## Quando Escolher Cada Abordagem ### Escolher Signal Store quando: - Se está construindo novas aplicações Angular 20+ - Se está gerenciando estado em nível de funcionalidade ou componente - Experiência do desenvolvedor e redução de boilerplate são prioridade - O time tem experiência limitada com NgRx - O tamanho do bundle importa ### Escolher NgRx Clássico quando: - Se está mantendo aplicações NgRx existentes - Se requer trilhas de auditoria rigorosas com logging de actions - Se está construindo fluxos de trabalho complexos com efeitos colaterais extensivos - Se precisa de depuração time-travel completa do Redux DevTools - O time tem experiência profunda em NgRx Para os [fundamentos de gerenciamento de estado](/technologies/angular/interview-questions/state-management-basics), entender ambas as abordagens prepara desenvolvedores para diversos codebases Angular. ## Conclusão - Signal Store reduz o boilerplate de gerenciamento de estado entre 60-70% comparado com NgRx clássico - NgRx clássico continua sendo a melhor escolha para aplicações empresariais que requerem trilhas de auditoria rigorosas e efeitos colaterais complexos - Ambas as abordagens podem coexistir na mesma aplicação, permitindo migração incremental - Os signals computados do Signal Store fornecem memorização automática sem definições explícitas de selectors - As features de store personalizadas (`signalStoreFeature`) permitem preocupações transversais reutilizáveis - Para novos projetos Angular 20+ em 2026, Signal Store deve ser a escolha padrão a menos que requisitos específicos demandem NgRx clássico --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/pt/blog/angular/ngrx-signal-store-vs-classic-ngrx-comparison