Como instalar, configurar e utilizar o Firebase em aplicações React Native

Interface final do projeto

Após começar a utilizar o Firebase em alguns projetos pessoais e profissionais, vejo como essas bibliotecas podem nos auxiliar e empoderar nossos aplicativos, principalmente quando não temos a estrutura de um backend, ou quando queremos ter um login ou banco de dados de forma mais simplificada por exemplo.

Por isso, decidi criar esse design/projeto exclusivamente para aprendermos a configurar o Firebase e seus pacotes em nossos projetos, além de explicar como utilizar o Auth para criarmos login com e-mail e senha, e o firestore para o armazenamento dos dados dos users.

O primeiro passo será iniciarmos o nosso projeto, com isso, resolvi criá-lo com o React Native CLI visto que o Expo esta com alguns problemas na ultima versão do SDK 65, principalmente relacionado a dependência @types/react onde ele entra em um loop dizendo que você não instalou a dependência, mesmo já estando instalada.

Para startar nosso projeto com TypeScript, rodaremos o seguinte comando:

npx react-native init nomeProjeto --template react-native-template-typescript

Como o projeto foi criado a partir da CLI, para rodar em nossos emuladores é necessário realizar o build do app no Android Studio e XCode ou rodando yarn android e yarn ios .

💡 Sempre que crio um projeto, eu também crio a pasta referente a ele no Github, assim consigo versionar e não perder o que tenho progredido no projeto.

Projeto criado e buildado com sucesso ✅

Interface do aplicativo padrão criado e emulado

Depois de criado e buildado o projeto, o próximo passo que realizo é iniciar as instalações do Firebase. Porém, antes de iniciar, você conhece a ferramenta?

O que é o Firebase?

É uma plataforma do Google que auxilia no desenvolvimento de aplicativos web e/ou mobile, de forma rápida e simples.

O Firebase é um BaaS (Backend as a Service), ou seja, provê a estrutura e o backend sem ter que desenvolver o backend de forma manual, além disso, oferece várias soluções como: armazenamento de arquivos, autenticação de usuários, banco de dados, analytics, feature-flags...

Para saber mais sobre a ferramenta, basta acessar as duas documentações disponíveis, a do react native firebase https://rnfirebase.io/ e a do próprio Firebase https://firebase.google.com/docs.

Quais são as vantagens do Firebase?

  • Possui uma versão gratuita e muito completa por sinal
  • Escalável
  • Possui suporte para diversos tipos de plataformas (iOS, Android, JavaScript e C++) utilizando a mesma API
  • Reduz o tempo de desenvolvimento já que entrega o backend pronto
  • Possui fácil implementação

Criando um projeto no Firebase Console

  1. Antes de iniciarmos a instalação de pacotes no código, necessitamos acessar o https://firebase.google.com/ para criar um novo projeto. Você pode utilizar uma conta Google para conectar-se, ou criar uma nova conta gratuita caso não tenha, e para isso, basta clicar em "Começar”.

Firebase Console

  1. Após realizarmos o login no Console do Firebase, clique em + Adicionar projeto

Adicionar projeto firebase console

Em seguida, digite um nome para o seu projeto e clique no botão continuar. Na próxima etapa, você pode deixar o Google Analytics ativado ou não e clicar no botão continuar.

Em Configurar o Google Analytics, selecione a opção "Default Account for Firebase" e clique no botão "Criar Projeto".

Pronto! Agora é só esperar o projeto ser criado. 🎉

Projeto criado no firebase console

Instalação do React Native Firebase App

Agora, vamos instalar o módulo React Native Firebase App. Pois, é ele quem faz a conexão da nossa aplicação com o Firebase.

Então, execute a instalação na raiz do projeto:

# Com npm
npm install --save @react-native-firebase/app

# Com Yarn
yarn add @react-native-firebase/app

Configuração no Android

Para realizar a configuração no Android, primeiramente necessitamos ir no console do Firebase para adicionar um novo aplicativo Android. Então, clique no ícone do Android.

Configurar aplicativo android

  1. Para registrar nosso app Android no primeiro passo, realizaremos as instruções abaixo e posteriormente clicaremos em Registar app para passarmos para as próximas etapas.

Adicionar firebase app android

a. Para encontrar o nome do pacote Android, basta acessarmos em nosso código o arquivo MainActivity.java e o nome estará na primeira linha do arquivo.

MainActivity.java file

b. Em apelido do app podemos colocar Android.

c. No campo certificado de assinatura SHA-1 não necessitaremos nesse exemplo, pois ele é obrigatório apenas em alguns cenários específicos, mas caso necessite gerar o certificado, digite no prompt o código abaixo e o certificado será gerado.

cd android
bash ./gradlew signinReport

Serão geradas várias chaves, mas a necessária para este campo é Variant: androiddebugkey - SHA1

SHA1 key

  1. Na próxima etapa, faremos o download do arquivo de configuração que é o google-services.json e clicar em Próxima.

a. Iremos baixá-lo e inserí-lo em nosso código dentro de /android/app/

Fazer o download do arquivo de configuraçao do firebase

  1. Posteriormente adicionaremos o SDK do Firebase em nosso aplicativo, ou seja, configuraremos o código nativo que irá conectar a nossa aplicação com o Firebase.

a. Primeiro vamos dentro do arquivo /android/build.gradle e adicionaremos dentro de buildscript:

buildscript {
 repositories {
   // Check that you have the following line (if not, add it):
   google()  // Google's Maven repository
 }
 dependencies {
   ...
   // Adicionar essa linha
   classpath("com.google.gms:google-services:4.3.13")

 }
}

allprojects {
 ...
 repositories {
   // Checar se você possui essa linha, caso não possuir, adicione-a:
   google()  // Google's Maven repository
   ...
 }
}

b. Posteriormente, iremos adicionar dentro do arquivo /android/app/build.gradle o seguinte trecho:

apply plugin: 'com.android.application'

// Adicionar essa linha
apply plugin: 'com.google.gms.google-services'

dependencies {
 // Importar o Firebase BoM se você for utilizar o analytics
 implementation platform('com.google.firebase:firebase-bom:30.3.1')

 // Adicionar a dependência para o Firebase SDK se você for utilizar o Analytics
 // Ao usar o BoM, não especifique as versões nas dependências do Firebase
  implementação 'com.google.firebase:firebase-analytics'
}

Configuração no iOS

Para realizar a configuração no iOS seguiremos o mesmo padrão do Android, primeiramente iremos ao console do Firebase, clicaremos em Adicionar app e então, clicaremos no ícone do iOS+.

Adicionar projeto iOS no firebase console

  1. Conforme configuramos no Android, preencheremos os campos abaixo e em seguida clicaremos em Registrar app para seguirmos para as próximas etapas.

Adicionar firebase em app iOS

a. Para encontrarmos o nome do ID do pacote Apple necessitamos abrir nosso projeto no XCode clicar em cima do nome do projeto e assim será aberto ao lado do nome, do lado direito, mais detalhes do projeto, e dentro da aba General conseguimos ver dentro de Bundle Identifier o nome que utilizaremos dentro do ID do pacote Apple.

bundle identifier XCode

b. No Apelido do app coloquei o nome de iOS

c. No campo Código da App Store você adicionará caso já tenha a conta da appStoreConect, mas é totalmente opcional

  1. Na próxima etapa, iremos realizar o download do arquivo de configuração que é o GoogleService-Info.plist e clicar em Próxima.

Fazer o download do arquivo googleservice-info.plist

a. Iremos baixá-lo e para inserí-lo dentro do projeto, abriremos novamente o XCode → clicaremos em cima do nome do projeto, clicaremos com o botão direito do mouse → selecionaremos Add Files to "nome do projeto"

Adicionar arquivos dentro do projeto

b. Selecionaremos o arquivo baixado e clicaremos em Add

googleServices-info.plist file

Prontinho, agora o arquivo já está adicionado:

Arquivo adicionado dentro do projeto

  1. Agora a partir da etapa 3 da documentação, não seguiremos exatamente como está descrito. Nesse passo, é solicitado que adicionemos o SDK do Firebase, mas todas as vezes que tentei realizar esse passo, o SDK de alguma forma fez o meu projeto ter alguns bugs, então preferi não instalá-lo, mas esteja a vontade para fazê-lo, se desejar. Ou seja, esse passo eu pulo.

Adicionar o SDK do firebase no projeto iOS

Na etapa de adicionar o código de inicialização, também faremos um pouco diferente do que é visualizado, porque nosso código iOS está em C++ e as opções exibidas são apenas para SwiftUI, Swift e Objective-C.

a. Para permitir que o Firebase use as credenciais no iOS, abra dentro do código o arquivo /ios/{projectName}/AppDelegate.m e adicionaremos a seguinte linha na parte superior do arquivo, logo abaixo de #import "AppDelegate.h":

#import "AppDelegate.h"

#import "Firebase.h"
#import "FirebaseCore.h"

b. Ainda nesse arquivo, adicionaremos o seguinte trecho de código:

- (BOOL)application:(UIApplication *)application
   didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

 // Adicionar essa configuração
 [FIRApp configure];

 return YES;
}

Instalação das bibliotecas do Firebase

Agora que nosso Firebase está instalado e devidamente configurado, instalaremos as bibliotecas que utilizaremos nesse projeto de login.

  1. A primeira lib a ser instalada será o Cloud Firestore, que é um banco de dados de documentos NoSQL. É escalonável e focado em desenvolvimento de aplicações móveis e web.

Principais benefícios:

  • Flexibilidade
  • Consultas expressivas
  • Atualizações em tempo real
  • Podemos utilizar a sincronização de dados para atualizá-los em qualquer dispositivo conectado
  • Suporte off-line
  • Armazena em cache os dados ativamente utilizados pelo aplicativo
  • Projetado para escalar

Assim, para podermos utilizá-lo necessitamos instalar a biblioteca da seguinte forma:

yarn add @react-native-firebase/firestore
  1. A segunda biblioteca que instalaremos será a de Auth para podermos dar vida as telas de login com e-mail e senha. Para instalá-la necessitamos rodar:
yarn add @react-native-firebase/auth

Pronto, agora sim, nosso Firebase está instalado, configurado, e com as bibliotecas necessárias também instaladas. Mas necessitamos rodar o pod install em nossa pasta iOS e posteriormente buildar novamente o projeto em nossos emuladores Android e iOS, visto que fizemos configurações em códigos nativos.

cd ios/ && pod install

Pode ser que ocorra um erro o rodar o pod install parecido com o abaixo: The Swift pod FirebaseCoreInternal depends upon GoogleUtilities, which does not define modules. To opt into those targets generating module maps (which is necessary to import them from Swift when building as static libraries), you may set use_modular_headers! globally in your Podfile, or specify :modular_headers => true for particular dependencies.

Basicamente temos que permitir vincular bibliotecas estáticas Swift, como o FirebaseCoreInternal e para isso adicionaremos o seguinte comando em nosso arquivo Podfile:

pod 'Firebase', :modular_headers => true
pod 'FirebaseCore', :modular_headers => true
pod 'FirebaseCoreInternal', :modular_headers => true
pod 'GoogleUtilities', :modular_headers => true

E depois buildar novamente o projeto nos emuladores Android e iOS, via prompt ou via Android Studio e XCode ou via prompt:

yarn ios

yarn android

Agora sim, tudo pronto para começarmos a utilizá-lo em nosso código.

Para iniciarmos a utilização das bibliotecas que instalamos do Firebase, criei o projeto Water Reminder no meu Github, que pode ser acessado pelo link: https://github.com/ildaneta/water-reminder.

Se vocês quiserem, podem clonar o projeto a partir da branch feature/screens , assim, toda a parte de telas, componentes e navegações já estarão configuradas, e será possível implementar as telas de SignIn, SignUp e Recovery password com o que aprenderemos em seguida.

Branch: https://github.com/ildaneta/water-reminder/tree/feature/screens.

Utilizando o Auth e Cloud Firestore

Para começarmos a utilizar o Auth do Firebase, iremos novamente até o console novamente, e no menu superior esquerdo clicaremos em Criação → Authentication

Auth firebase console

Logo em seguida, clicaremos em Vamos começar → escolher a opção de E-mail/senha

image

Ativaremos a primeira opção e logo após, clicar em Salvar.

image

Configuramos nosso Auth no console do Firebase, agora criaremos nosso Cloud Firestore, ou seja, nosso banco de dados, que salvará os dados dos users. Para isso, iremos novamente no menu superior esquerdo, clicaremos em Firestore Database e logo após em Criar banco de dados.

image

Escolha o modo de produção → Avançar, logo após, o local do Cloud Firestore e Ativar.

image

Assim que nosso banco de dados estiver criado, iremos dentro de Regras e apagaremos a parte : if false; do lado de ,write , em seguida, clicar em Publicar, porque assim, salvaremos dados no banco de dados, mesmo quando o usuário ainda não estiver logado.

rules_version = '2';
service cloud.firestore {
 match /databases/{database}/documents {
   match /{document=**} {
     allow read, write: // if false; // apagar
   }
 }
}

image

O próximo passo é configurar uma coleção, que seria o mesmo de uma tabela, nesse caso, será nossa tabela de users. Daremos o nome da coleção e clicaremos em Próxima.

image

Para criar uma collection pelo Firebase é necessário inserir um id do documento, nesse caso, podemos clicar em Código automático e Salvar, assim nossa collection estará criada.

Agora chegou o momento do código. 👩🏻‍💻

Para essa aplicação, como tudo está relacionado a parte de login, criei um hook chamado useAuth onde estarão todas as funções necessárias para o login funcionar corretamente, que serão: signUp(responsável por criar um usuário), signIn(responsável por realizar o login), singOut(responsável por deslogar o usuário), recoveryPassword(responsável por resetar a senha do user via e-mail), isLoading(retornará se está havendo um carregamento), e user(retorna o id e username do usuário).

Criando um Usuário com Firebase Auth e adicionando-o dentro da collection de Users do Firebase Firestore.

Para criar o usuário com o auth é necessário chamar o método do auth .createUserWithEmailAndPassword(email, password) passando o email e senha digitada pelo user. Após isso, guardo os dados no firestore, chamando o método firestore(), para salvar os dados na collection de users, utilizo o método .collection('users') passando o nome da collection.

Aqui tem um detalhe importante, pois para adicionar dados em uma collection posso utilizar duas formas, uma com o método .add(), assim criamos um novo dado na collection com um id aleatório criado pelo Firebase, mas nesse cenário eu precisava que o id do documento da collection fosse igual ao id do user criado no auth, com isso, ao adicionar eu utilizo o método .doc(uid) passando o id da conta do usuário dentro do auth, e chamo o método .set() passando o id do user e o nome de cadastro que serão armazenados na collection de users do firestore.

const signUp = async ({ username, email, password }: SignUpData) => {
  if (!username || !email || !password) {
    return Alert.alert(
      'SignUp',
      'Enter username, e-mail and password to create your account.'
    )
  }

  if (password.length < 6) {
    return Alert.alert('SignUp', 'Password cannot be less than 6 characters.')
  }

  try {
    setIsLoading(true)
    await auth()
      .createUserWithEmailAndPassword(email, password)
      .then((account) => {
        const { uid } = account.user

        firestore()
          .collection('users')
          .doc(uid)
          .set({
            id: uid,
            username,
          })
          .then(() => {
            Alert.alert('SignUp', 'Account created with sucess!', [
              {
                text: 'Ok',
                onPress: () => navigation.navigate('SignIn'),
              },
            ])
          })

        setIsLoading(false)
      })
      .catch((error) => {
        const { code } = error

        if (code === 'auth/email-already-in-use') {
          return Alert.alert('SignUp', 'E-mail is already in use')
        }
        setIsLoading(false)
      })
      .finally(() => {
        setIsLoading(false)
      })
  } catch (error) {}
}

Basicamente são esses os passos para criar um usuário com as duas libs, o restante do código são apenas algumas verificações e redirecionamentos que realizo.

Realizar o login de um usuário já cadastrado na base dados do auth e firestore

Os passos para realizar o login são bem parecidos ao de criar um novo user, o que mudam são os métodos utilizados.

No auth, ao invés de utilizar o .createUserWithEmailAndPassword() para criar, utilizaremos o .signInWithEmailAndPassword(email, password) para realizar o login, e para trazer do firestore esse user já cadastrado, utilizamos o método .get() passando antes qual a collection que iremos buscar o dado e qual o id do documento que será recuperado.

Outro passo que realizo no signIn é salvar os dados do usuário que são o id e o nome dentro do AsyncStorage assim consigo verificar se o usuário já está logado para que não precise passar novamente pela tela de signIn.

const signIn = async ({ email, password }: SignInData) => {
  if (!email || !password) {
    return Alert.alert('SignIn', 'E-mail and password is required.')
  }

  setIsLoading(true)

  auth()
    .signInWithEmailAndPassword(email, password)
    .then((response) => {
      const { uid } = response.user
      firestore()
        .collection('users')
        .doc(uid)
        .get()
        .then(async (profile) => {
          const { id, username } = profile.data() as IUser

          if (profile.exists) {
            const userData = {
              id,
              username,
            }

            setUser(userData)

            AsyncStorage.setItem(USER_COLLECTION, JSON.stringify(userData))
            navigation.navigate('Home')
          }

          setIsLoading(false)
        })
    })
    .catch((error) => {
      const { code } = error

      if (code === 'auth/wrong-password') {
        return Alert.alert(
          'SignIn',
          'The password is invalid or the user does not have a password.'
        )
      }

      if (code === 'auth/user-not-found') {
        Alert.alert(
          'SignIn',
          'There is no user record corresponding to this e-mail.'
        )
      }
    })
    .finally(() => setIsLoading(false))
}

Realizar a recuperação de senha do user

Para enviar um e-mail de recuperação de senha e assim o usuário poder modificá-la, utilizamos o método do auth .sendPasswordResetEmail(email), esse é bem simples, porque o firebase cuida de todo o restante, que seria enviar o e-mail e salvar a nova senha cadastrada. No código abaixo além de chamar o método para recuperar a senha, apresento alertas em caso de sucesso e erro.

const recoveryPassword = async ({ email }: RecoveryPasswordData) => {
  if (!email) {
    return Alert.alert('Recovery password', 'E-mail is required.')
  }

  await auth()
    .sendPasswordResetEmail(email)
    .then(() => {
      Alert.alert(
        'Recovery password',
        'We have sent a link to your email to reset your password.',
        [
          {
            text: 'Ok',
            onPress: () => navigation.navigate('SignIn'),
          },
        ]
      )
    })
    .catch((error) => {
      const { code } = error

      if (code === 'auth/user-not-found') {
        Alert.alert(
          'Recovery password',
          'It was not possible to send the password reset to your e-mail, because the e-mail you entered was not registered.'
        )
      }
    })
}

Deslogar o user da aplicação

Por fim, mas não menos importante, seria o passo de realizar o logout do usuário do aplicativo, e para isso chamamos o método do auth .signOut(). Como eu também salvo no AsyncStorage os dados do user quando ele loga, nesse momento eu também os removo e navego novamente para a tela de SignIn.

const signOut = async () => {
  setIsLoading(true)
  await auth().signOut()
  await AsyncStorage.removeItem(USER_COLLECTION)
  setUser(null)
  setIsLoading(false)

  navigation.navigate('SignIn')
}

Basicamente são esses os passos que temos que realizar para ter a solução de login completa utilizando o firebase.

Lembrando que vocês podem acompanhar todo o progresso / implementação do aplicativo pelo projeto no Github: https://github.com/ildaneta/water-reminder

Além disso, esse projeto é open source, ou seja, o código é aberto e vocês podem utilizá-lo a vontade, além disso, é uma ótima oportunidade para realizar contribuições, ou seja, vocês podem fazer esse app criar vida, enviar solicitações de pull request para mim, inserir testes, enfim, colocar todos os conhecimentos em prática e ainda contribuir em um projeto da comunidade.

Espero que tenham gostado do artigo, apesar de bem grande, tentei explicar no máximo de detalhes possíveis como instalar, configurar e utilizar o Firebase, que ja é uma das minhas libs favoritas, e que no começo tive alguns probleminhas para realizar a instalação inicial, que para mim é o mais complexo.

Até o próximo artigo pessoal! 🫶🏻