Ao atualizar para o Angular 21 e tentar utilizar o SDK modular do Firebase (firebase/firestore), é comum se deparar com erros de “Provedor não encontrado” ou conflitos de tipos internos. Neste artigo, vamos dissecar a causa desses erros e como resolvê-los usando as melhores práticas atuais.


1. O Erro de Provedor: NG0201 Link para o cabeçalho

Mensagem: ERROR ɵNotFound: NG0201: No provider found for Firestore

A Causa Link para o cabeçalho

Desde o Angular 17, a arquitetura padrão é Standalone. Isso significa que não existe mais o app.module.ts. Se você tenta usar o inject(Firestore) em um componente, mas não registrou o serviço no bootstrap da aplicação, o Angular não sabe como instanciá-lo.

A Solução Link para o cabeçalho

Você deve configurar os provedores no arquivo app.config.ts. Certifique-se de importar as funções de inicialização do @angular/fire.

// src/app/app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
import { provideFirestore, getFirestore } from '@angular/fire/firestore';
import { environment } from '../environments/environment';

export const appConfig: ApplicationConfig = {
  providers: [
    // Ordem crucial: primeiro inicializa o App, depois os serviços
    provideFirebaseApp(() => initializeApp(environment.firebase)),
    provideFirestore(() => getFirestore()),
  ]
};

Certifique-se de que no main.ts, o bootstrapApplication(App, appConfig) está recebendo este objeto de configuração.


2. O Conflito de Tipos: _Query vs _CollectionReference Link para o cabeçalho

Mensagem: ERROR FirebaseError: Expected type '_Query', but it was: a custom _CollectionReference object

A Causa Link para o cabeçalho

Este é o erro mais frustrante. Ele ocorre quando há uma “mismatch” (descompasso) de instâncias:

  1. Você injeta o Firestore através do @angular/fire.

  2. Você tenta passar esse objeto injetado para funções (como query, collection, getDocs) importadas diretamente de firebase/firestore (o SDK puro).

Internamente, o @angular/fire envolve o Firestore em um wrapper. O SDK puro não reconhece esse wrapper como uma instância válida, lançando o erro de tipo.

A Solução Definitiva Link para o cabeçalho

Para manter a sintaxe modular (Promises/async-await) que você deseja, a regra de ouro é: Importe as funções operacionais do @angular/fire/firestore, mas mantenha a lógica de execução.

As funções exportadas pelo @angular/fire/firestore possuem a mesma assinatura do SDK puro, mas são cientes do sistema de injeção do Angular.


O Código Final (Boa Prática) Link para o cabeçalho

Aqui está como o componente deve ficar para evitar ambos os erros, utilizando Signals para performance:

import { Component, inject, OnInit, signal } from '@angular/core';
import { JsonPipe } from '@angular/common';
// SOLUÇÃO: Importe as funções do wrapper do AngularFire
import { 
  Firestore, 
  collection, 
  query, 
  getDocs 
} from '@angular/fire/firestore';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [JsonPipe],
  //templateUrl: './app.html',
  //styleUrl: './app.css'
  template: `
    @for (item of dados(); track item.id) {
      <p>{{ item.nome }}</p>
    }
  `
})
export class App implements OnInit {
  // Injeção limpa e segura
  private readonly db: Firestore = inject(Firestore);
  
  // Estado reativo com Signals
  protected dados = signal<any[]>([]);

  async ngOnInit() {
    await this.fetchFirestoreData();
  }

  async fetchFirestoreData() {
    try {
      const colecaoRef = collection(this.db, 'sua-colecao');
      const q = query(colecaoRef);
      
      // Uso de async/await perfeitamente compatível
      const querySnapshot = await getDocs(q);
      
      const results = querySnapshot.docs.map(doc => ({
        id: doc.id,
        ...doc.data()
      }));

      this.dados.set(results);
    } catch (e) {
      console.error("Erro na busca:", e);
    }
  }
}

Resumo para o desenvolvedor Link para o cabeçalho

  1. NG0201? Verifique se o provideFirestore() está no app.config.ts.

  2. _Query mismatch? Pare de importar de firebase/firestore e passe a importar de @angular/fire/firestore.

  3. Template parou de atualizar? Troque variáveis comuns por Signals para garantir que o Angular detecte a mudança após o await.