Publicado em
- 5 minutos de leitura
Gerenciamento de Estado no Angular: Global vs Local State
Gerenciamento de estado é um dos pilares mais importantes no desenvolvimento de aplicações Angular modernas.
Ele define como os dados fluem pela aplicação e como os componentes reagem às mudanças nessas informações, garantindo que a interface do usuário esteja sempre sincronizada com a lógica de negócio de forma previsível.
Neste artigo, vamos explorar a diferença fundamental entre o Global State e o Local State.
Entender quando usar um serviço compartilhado por toda a aplicação ou uma instância restrita a um componente é essencial para criar sistemas escaláveis, performáticos e fáceis de manter no longo prazo.
O que é gerenciamento de estado no Angular
No Angular, gerenciar o estado significa controlar os dados que determinam o comportamento e a aparência da sua aplicação em um determinado momento.
Isso inclui desde informações simples, como se um menu lateral está aberto, até dados complexos vindos de uma API, como o perfil de um usuário ou uma lista de produtos.
Uma boa gestão de estado permite que diferentes partes da aplicação se comuniquem de forma eficiente sem criar uma “teia de aranha” de conexões confusas.
Usando Signals e Services, conseguimos criar um fluxo de dados reativo onde o Angular sabe exatamente qual parte da tela precisa ser atualizada quando um valor muda, sem desperdiçar processamento.
O que é Global State
O Global State (Estado Global) refere-se a informações que precisam estar disponíveis durante todo o tempo de vida da aplicação, do momento que ela abre até o fechamento da aba.
Geralmente, esses dados são necessários em múltiplos lugares independentes, como em diferentes rotas ou componentes que não possuem relação direta entre si.
Esses estados são implementados usando serviços com a propriedade providedIn: 'root'. Isso cria uma única instância (singleton) que é compartilhada por todos os componentes do sistema.
Se você atualizar um valor nesse serviço em uma página de “Configurações”, a mudança refletirá imediatamente no “Header” ou em qualquer outra parte que consuma esse mesmo serviço.
Exemplo: Gerenciando Autenticação (Global State)
Para estados globais, como o de um usuário logado, usamos uma Store centralizada baseada em Signals para garantir reatividade e performance.
import { Injectable, signal, computed } from '@angular/core'
@Injectable({
providedIn: 'root'
})
export class AuthService {
// Estado privado usando signals para controle total
private userSignal = signal<string | null>(null)
// Exposição do estado de forma segura e somente leitura
user = computed(() => this.userSignal())
isLoggedIn = computed(() => !!this.userSignal())
login(userName: string) {
this.userSignal.set(userName)
}
logout() {
this.userSignal.set(null)
}
}
Neste exemplo, qualquer componente que injetar o AuthService terá acesso ao mesmo signal de user. Como é um Singleton, o estado persiste mesmo que o usuário navegue entre diferentes rotas da aplicação.
O que é Local State
O Local State (Estado Local) é o oposto: ele tem um tempo de vida limitado e está vinculado à existência de uma parte específica da interface.
Ele nasce quando o componente (ou rota) é carregado e morre (é destruído) quando o usuário sai daquela tela. É o estado “efêmero”, usado para controlar processos temporários.
Para implementar o Local State com serviços, nós os registramos diretamente no array de providers do componente, em vez de usar o providedIn: 'root'.
Isso garante que cada vez que o componente for instanciado, o Angular criará uma cópia nova e exclusiva do serviço para aquele componente e seus filhos, descartando-a automaticamente depois.
Exemplo: Gerenciando um Stepper (Local State)
Imagine um formulário de várias etapas (wizard). Os dados desse formulário só importam enquanto o usuário está preenchendo o wizard.
import { Injectable, signal } from '@angular/core'
@Injectable() // Sem 'providedIn: root' para permitir múltiplas instâncias
export class StepperService {
currentStep = signal(1)
stepData = signal({ name: '', email: '' })
next() {
this.currentStep.update((s) => s + 1)
}
previous() {
this.currentStep.update((s) => s - 1)
}
}
// No componente filho
@Component({
selector: 'app-step-one',
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [FormsModule],
template: `
<input type="text" [(ngModel)]="stepperService.stepData().name" />
<button (click)="stepperService.next()">Próximo</button>
`
})
export class StepOneComponent {
stepperService = inject(StepperService)
}
// No componente pai
@Component({
selector: 'app-registration-stepper',
providers: [StepperService], // O serviço nasce e morre com este componente
imports: [StepOneComponent],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="stepper-container">
<p>Passo: {{ stepperService.currentStep() }}</p>
<app-step-one />
</div>
`
})
export class RegistrationStepperComponent {
stepperService = inject(StepperService)
}
Ao registrar o StepperService no componente pai, todos os componentes filhos (app-step-one, etc.) podem injetar esse mesmo serviço e compartilhar o estado do formulário de forma organizada, mas sem expor esses dados para o resto da aplicação.
Quando usar cada um
Global State
Para informações que definem a sessão ou o ambiente global do usuário.
Exemplos clássicos são:
- tokens de autenticação
- configurações de tema (escuro ou claro)
- preferências de idioma
- um carrinho de compras que deve persistir enquanto o usuário navega livremente pela loja.
Local State
Para fluxos de trabalho isolados e componentes complexos.
Se você tem:
- uma tabela com filtros específicos
- um modal de edição
- um processo de checkout
Esses dados não precisam “sujar” a memória global. Ao manter o estado local, você evita bugs onde dados de uma tela anterior aparecem “vazados” em uma nova tela.
Conclusão
Dominar a distinção entre estado global e local é o que diferencia um desenvolvedor de aplicações simples de um especialista em arquitetura Angular.
Ao escolher a estratégia correta, você melhora a performance da aplicação, já que o Angular não precisa monitorar mudanças globais desnecessárias, e torna seu código muito mais fácil de testar, pois as dependências ficam claras.
Lembre-se sempre de avaliar o ciclo de vida da informação antes de criar um serviço.
Se o dado deve sumir quando o usuário fecha uma aba ou sai de uma tela, mantenha-o local através dos providers do componente.
Com o uso de Signals e a injeção de dependência poderosa do Angular, essa organização se torna natural e garante aplicações extremamente robustas.
Assine nossa Newsletter
Receba novos posts como esse na sua caixa de e-mail!
Sobre o autor