Imagen de fondo tecnológico con logotipos de Firebase y React, y texto que dice 'AUTENTICACIÓN Y BASE DE DATOS CON FIREBASE - REACT

Cómo integrar Firebase en tu aplicación React para autenticación y base de datos

En este artículo, vamos a explorar cómo integrar Firebase en tu aplicación React para autenticación y base de datos. Lo haremos en dos partes: primero configuraremos Firebase en la consola y luego integraremos el código en Visual Studio Code.

Usaremos como ejemplo un proyecto de una biblioteca virtual para anime y manga, al que llamaremos Animan. Para comenzar, crea una cuenta en Firebase o inicia sesión si ya tienes una. Una vez en la interfaz de Firebase, selecciona "Crear proyecto".

Captura de pantalla de firebase

Coloca en nombre de tu preferencia, seleccionas "continuar". 

pasos para configurar firebase

Como es un proyecto de prueba deshabilitamos Google Analytics, pero si deseas activarlo no hay problema. 

opciones para configurar el proyecto en firebase

En unos segundos estará listo. 

una vez el proyecto esta listo, muestra el mensaje de continuar

Una vez creado el proyecto, vamos a la configuración del mismo en la consola de Firebase. Ve a tu proyecto y, en la sección de "Project settings" (configuración del proyecto) en la parte superior izquierda, haz clic en el ícono de engranaje. En la pestaña "General", desplázate hacia abajo y en "Tus aplicaciones", selecciona "Configurar Firebase en la Web". 

Configuración del proyecto en firebase

configurar proyecto web en firebase

Luego, se mostrará una ventana con opciones para registrar el proyecto. Aquí se te dará la opción de incluir un dominio o no. En este caso, solo registraremos el proyecto.configuración web del proyecto en firebase

Una vez registrado, se te mostrarán los pasos a seguir para la configuración del proyecto y los datos correspondientes. Copia la configuración que aparece, la cual es una clave JSON con tus credenciales de Firebase.congifuracion web del proyecto firebase

Por otro lado, debemos habilitar los servicios de autenticación y base de datos. Primero, en la sección de Authentication en Firebase Console, hacemos clic en "Empezar" y en la pestaña "Método de inicio de sesión", habilitamos el método de "Correo electrónico/contraseña" para luego hacer clic en "Guardar".

opciones de compilación de firebase

configuración de la autenticación en firebase

configuración de autentificación en firebase

Listo, puedes visualizar que ya está activa la autenticación por correo/contraseña. Si deseas agregar otro método de autenticación, como Google, puedes hacerlo en la opción de agregar otro proveedor.

configuración de autentificación en firebase

Para este proyecto, optaremos por usar Firebase Realtime Database debido a su simplicidad y adecuación para proyectos pequeños y sencillos. En cambio, Firestore Database es más adecuado para estructuras de datos más complejas y aplicaciones que requieren consultas avanzadas y mejor escalabilidad. Para obtener más detalles sobre las diferencias entre Firebase Realtime Database y Firestore Database, puedes consultar el siguiente artículo. 

Después, en el menú lateral de Firebase Console, vamos a "Realtime Database", creamos la base de datos en el modo de prueba (suficiente para desarrollo), hacemos clic en "Siguiente" y finalmente en habilitar. 

configuración de la base de datos firebase

configuración de la db firebase

Por defecto, se escoge la ubicación más cercana. Sin embargo, si el usuario lo requiere, se puede cambiar esta opción.

configuración de db firebase

configuración db firebase

Con las configuraciones en la consola de Firebase completas, es momento de pasar al código. Primero, instalamos Firebase utilizando npm:

npm install firebase

Después, creamos un archivo llamado firebaseConfig.ts en la carpeta src de nuestro proyecto. En este archivo, pegamos la configuración proporcionada anteriormente por Firebase.

Importante: Ingresas a la consola de Firebase, y en Realtime Database vas a visualizar la URL, esta se debe agregar a la configuración en el archivo firebaseConfig.ts consola firebase

databaseURL: "https://animan-ecfce-default-rtdb.firebaseio.com", 

Debería verse algo así:

Código de la configuración de firebase

Una vez configurado Firebase y Realtime Database, vamos al código. 

Configuración de Firebase en el Código

Después de haber configurado Firebase en la consola y habilitado los servicios necesarios, es momento de integrarlo en nuestro código.

1. Instalación de Firebase

Para poder utilizar Firebase en nuestro proyecto React, necesitamos instalar el paquete oficial de Firebase utilizando npm. En la terminal, dentro de la carpeta de nuestro proyecto, ejecutamos:

 
npm install firebase

Este comando descargará e instalará Firebase en nuestro proyecto, permitiéndonos utilizar sus servicios.

2. Creación del Archivo de Configuración

Una vez instalado Firebase, debemos crear un archivo donde almacenaremos la configuración de nuestra aplicación. En la carpeta src, creamos un archivo llamado firebaseConfig.tsy pegamos la configuración proporcionada por Firebase.

El contenido de este archivo debe seguir la siguiente estructura:

import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getDatabase } from "firebase/database";

const firebaseConfig = {
  apiKey: "TU_API_KEY",
  authDomain: "TU_AUTH_DOMAIN",
  databaseURL: "URL"
  projectId: "TU_PROJECT_ID",
  storageBucket: "TU_STORAGE_BUCKET",
  messagingSenderId: "TU_MESSAGING_SENDER_ID",
  appId: "TU_APP_ID",
  databaseURL: "TU_DATABASE_URL",
};
// Inicializamos Firebase
const app = initializeApp(firebaseConfig);
// Exportamos los servicios necesarios
export const auth = getAuth(app);  // Para la autenticación
export const db = getDatabase(app); // Para Realtime Database
 

Nota : Recuerda reemplazar los valores de firebaseConfigcon los datos reales de tu proyecto en Firebase.

Este archivo inicializa Firebase en nuestra aplicación y exporta los módulos de autenticación ( auth) y base de datos ( database) para que podamos usarlos en otros archivos.

3. Implementación de la Autenticación

Para manejar la autenticación de manera eficiente, crearemos un contexto que almacenará la información del usuario y proporcionará funciones para iniciar y cerrar sesión.

En la carpeta contexts, creamos un archivo llamado AuthContext.tsxcon el siguiente código:

import React, { createContext, useContext, useEffect, useState } from "react";
import { User, onAuthStateChanged, signOut } from "firebase/auth";
import { auth } from "../firebaseConfig";

interface AuthContextProps {
  user: User | null;
  loading: boolean;
  logout: () => Promise;
}

const AuthContext = createContext(undefined);

export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
      setUser(currentUser);
      setLoading(false);
    });
    return () => unsubscribe();
  }, []);



   // Implementación de logout
  const logout = async () => {
    try {
      await signOut(auth); // Cierra la sesión en Firebase
      setUser(null); // Limpia el estado del usuario
    } catch (error) {
      console.error("Error al cerrar sesión:", error);
    }
  };

  return (
    
      {children}
    
  );
};

export const useAuth = (): AuthContextProps => {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error("useAuth debe usarse dentro de un AuthProvider");
  }
  return context;
};

Para gestionar la autenticación de usuarios en el proyecto, se implementó un contexto de autenticación usando React y Firebase. Esto centraliza la gestión del usuario y facilita el acceso a su información en toda la aplicación sin necesidad de prop-drilling.

Importaciones: Se importaron createContextuseContextuseEffect, y useState desde React, y onAuthStateChangedsignOut, y auth desde Firebase.

Interfaz AuthContextProps: Define tres propiedades clave:

  • user: Almacena el usuario autenticado o null si no hay sesión.
  • loading: Indica si la aplicación está verificando la autenticación.
  • logout: Función asíncrona para cerrar sesión.

Creación del contexto: Se creó el contexto con createContext<AuthContextProps | undefined>(undefined), lo que obliga a verificar su existencia antes de usarlo.

Componente AuthProvider: Encargado de proveer el contexto de autenticación. Dentro de él:

  • Se definieron dos estados: user (usuario autenticado) y loading (verificación de sesión).
  • Se usó useEffect con onAuthStateChanged para escuchar cambios en la sesión del usuario, actualizando user y cambiando loading a false una vez verificada la sesión.
  • Se implementó una función de limpieza unsubscribe() para evitar fugas de memoria.
  • Función logout: Cierra la sesión del usuario llamando a signOut(auth) y actualiza user a null. Captura y muestra errores en la consola si ocurren.
  • Provisión del contexto: Los valores userloading, y logout se pasaron al AuthContext.Provider, permitiendo que cualquier componente dentro de AuthProvider acceda a ellos.
  • Hook useAuth: Facilita el acceso al contexto en otros componentes. Verifica si el contexto existe y lanza un error si se usa fuera de AuthProvider.

4. Creación del Servicio de Base de Datos

Para almacenar y gestionar los datos de nuestra biblioteca virtual de anime, utilizaremos Firebase Realtime Database. En la carpeta services, creamos un archivo llamado realtimeDatabaseService.ts, el cual contendrá las funciones para interactuar con la base de datos.

import { db } from "../firebaseConfig";
import { ref, push, get, onValue, off, child } from "firebase/database";
import { auth } from "../firebaseConfig";

// Función para agregar un nuevo anime
export const addAnime = async (title: string, status: string) => {
    try {
        const animesRef = ref(db, "animes");
        await push(animesRef, {
            Title: title,
            Status: status
        });
        console.log("Anime agregado correctamente");
    } catch (error) {
        console.error("Error al agregar anime:", error);
    }
};

// Función para obtener todos los animes
export const getAnimes = async () => {
    try {
        // Verificar si el usuario está autenticado
        if (!auth.currentUser) {
            console.log("Usuario no autenticado");
            return null;
        }

        const snapshot = await get(child(ref(db), "animes"));
        if (snapshot.exists()) {
            return snapshot.val();
        } else {
            console.log("No hay datos disponibles.");
            return null;
        }
    } catch (error) {
        console.error("Error al obtener los animes:", error);
        return null;
    }
};
// Función para escuchar cambios en la colección "animes"
export const listenToAnimes = (callback: (animes: Record | null) => void) => {
    const animesRef = ref(db, "animes");
    const unsubscribe = onValue(animesRef, (snapshot) => {
        if (snapshot.exists()) {
            callback(snapshot.val());
        } else {
            callback(null);
        }
    });

    // Devuelve una función para cancelar la suscripción
    return () => off(animesRef, "value", unsubscribe);
};

Se implementaron funciones para interactuar con Firebase Realtime Database, permitiendo agregar, obtener y escuchar cambios en la lista de animes en tiempo real.

Importaciones: Se utilizaron métodos de Firebase como refpushgetonValueoff, y child, junto con auth para validar la autenticación del usuario.

Agregar un anime (addAnime):

  • Recibe el título y estado del anime.
  • Usa push en la referencia ref(db, "animes") para añadir un nuevo anime.
  • Muestra un mensaje de éxito o error en la consola.

Obtener la lista de animes (getAnimes):

  • Verifica si el usuario está autenticado con auth.currentUser.
  • Usa get con child(ref(db), "animes") para recuperar los animes.
  • Devuelve los datos o null si no hay información disponible.

Escuchar cambios en tiempo real (listenToAnimes):

  • Recibe un callback para pasar los datos actualizados.
  • Usa onValue en ref(db, "animes") para escuchar cambios.
  • Retorna una función para cancelar la suscripción con off, optimizando el uso de recursos.

5. Creación de Pages y Componentes 

En este caso creamos  tres pages y dos componentes con relación a nuestra temática, pero dependerá de los alcances y preferencias de tu proyecto.

En la carpeta Pages, creamos tres archivos, Register.tsx, Login.tsx,  Dashboard.tsx.

  • El componente Register.tsx es una página que proporciona la interfaz y la lógica para el registro de usuarios en la aplicación. Para gestionar el estado, se utilizan dos variables: email y password, que almacenan los valores ingresados en los campos del formulario. También se usa useNavigate para redirigir al usuario a la página de dashboard una vez que el registro se complete con éxito.
  • Al enviar el formulario, la función handleRegister evita el comportamiento por defecto del navegador y llama a createUserWithEmailAndPassword de Firebase Authentication, utilizando los datos ingresados. Si el registro es exitoso, el usuario es redirigido al dashboard. En caso de error, se maneja la excepción y se muestra un mensaje en la consola.

Captura de código

  • El componente Login.tsx es una página diseñada para que los usuarios puedan iniciar sesión en la aplicación. En primer lugar, se utilizan los estados email y password para almacenar los datos ingresados por el usuario en los campos del formulario. También se emplea useNavigate para redirigir al usuario al dashboard una vez que haya iniciado sesión con éxito.
  • La función handleLogin se ejecuta cuando el usuario envía el formulario. Esta función evita el comportamiento predeterminado del navegador y llama a signInWithEmailAndPassword de Firebase Authentication, utilizando las credenciales proporcionadas. Si la autenticación es exitosa, el usuario es redirigido al dashboard. En caso de error, se captura la excepción y se muestra un mensaje en la consola.

Captura de código

El componente Dashboard.tsx es la página principal de la aplicación, donde los usuarios pueden gestionar su lista de animes y mangas.

  • En primer lugar, se utiliza el hook useAuth para obtener la función logout, que permite cerrar sesión, y useNavigate para redirigir al usuario a la página de inicio de sesión tras desloguearse.
  • La función handleLogout se encarga de ejecutar logout() y, en caso de éxito, lleva al usuario de vuelta a /login. Si ocurre un error, este se muestra en la consola.

captura de código react

 A su vez, se han creado dos componentes principales para gestionar la lista de animes: AddAnime y AnimeList.

  • El componente AddAnime permite a los usuarios agregar nuevos animes a la base de datos. Para ello, define dos estados: title, que almacena el nombre del anime, y status, que indica su estado (Visto, En progreso o Pendiente). Al enviar el formulario, la función handleAddAnime llama a addAnime para guardar los datos en Firebase. Luego, los campos se restablecen para permitir nuevas entradas. La interfaz incluye un campo de texto para el nombre y un select para elegir el estado, junto con un botón de envío.

Captura de código

  • Por otro lado, el componente AnimeList muestra la lista de animes registrados en la base de datos en tiempo real. Usa el contexto de autenticación para asegurarse de que solo los usuarios autenticados puedan ver los datos. Al montarse, la función listenToAnimes establece una suscripción que escucha cambios en la base de datos y actualiza el estado animes con la información recibida. Cada anime se representa en un li, mostrando su título y estado. Si no hay animes registrados, se muestra un mensaje indicándolo.

Captura de código

 6. Rutas

Para gestionar la navegación en nuestra aplicación, instalamos la biblioteca React Router, lo que nos permite definir rutas y controlar el acceso a diferentes páginas.

En el archivo App.tsx, importamos BrowserRouter (alias Router), Routes y Route de react-router-dom para estructurar la navegación. También incluimos Navigate para redirigir a los usuarios en función de su estado de autenticación.

Dentro del componente App, obtenemos el usuario autenticado y su estado de carga a través del hook useAuth. Si la aplicación aún está cargando, mostramos un mensaje de "Cargando...".

Luego, definimos las rutas de la aplicación:

  • Si el usuario no ha iniciado sesión, puede acceder a /login y /register. De lo contrario, será redirigido a /dashboard.
  • Si el usuario está autenticado, se le permite entrar a /dashboard, pero si no lo está, será redirigido a /login.
  • Cualquier ruta desconocida llevará automáticamente a /login.

captura de código React

Tambien se uso Tailwind Css, pero todo depene de la libreria y estilo que prefieras, aca podras encontrar el repositorio si deseas practicar. 

Integrar Firebase en una aplicación React es un proceso que requiere configurar la consola de Firebase, habilitar la autenticación y la base de datos, y luego conectar estos servicios al código del proyecto. En este artículo, hemos visto cómo hacerlo paso a paso, desde la instalación de Firebase hasta la implementación de un sistema de autenticación y almacenamiento de datos en tiempo real con Realtime Database.

Al estructurar la aplicación con contextos para la autenticación y servicios específicos para la base de datos, logramos una separación clara de responsabilidades, lo que facilita la escalabilidad y el mantenimiento del código. Además, el uso de React Router permite gestionar la navegación de manera eficiente, asegurando que solo los usuarios autenticados puedan acceder a ciertas secciones de la aplicación.

 

 

Code In Progress with ❤️ by Juan Pablo Amador