Saltar a contenido

React con Firebase

Firebase es una plataforma de desarrollo que incluye múltiples servicios útiles para aplicaciones modernas. En este apartado nos centraremos en la configuración e implementación de la autenticación.

Requisitos previos

Crear un proyecto en Firebase

  1. Inicia sesión en Firebase Console.
  2. Haz clic en "Añadir Proyecto".
  3. Configura el nombre del proyecto y acepta las condiciones de uso.
  4. Haz clic en "Crear proyecto" y espera a que se configure.

Configurar la aplicación en Firebase

  1. En el proyecto de Firebase, selecciona "Añadir una aplicación" y elige Web.
  2. Asigna un nombre a tu aplicación.
  3. Haz clic en "Registrar aplicación".
  4. Copia el fragmento de configuración de Firebase que se te proporciona, lo utilizaremos más adelante en el código.

Añadir Firebase al proyecto React

Primero, instala el paquete de Firebase en tu proyecto:

npm install firebase

Configurar Firebase en el proyecto

Crea un archivo src/config/Firebase.jsx y agrega el código de configuración:

// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";

// Your web app's Firebase configuration
const firebaseConfig = {
  apiKey: "TU_API_KEY",
  authDomain: "TU_AUTH_DOMAIN",
  projectId: "TU_PROJECT_ID",
  storageBucket: "TU_STORAGE_BUCKET",
  messagingSenderId: "TU_MESSAGING_SENDER_ID",
  appId: "TU_APP_ID",
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);

Próximos pasos

En este punto, ya tienes configurada la base para conectar tu aplicación a Firebase. A continuación:

  • Configuraremos el sistema de autenticación en Firebase Console.
  • Implementaremos la lógica de inicio de sesión y registro en React.

Crear un usuario de prueba en Firebase

  1. En Firebase Console, selecciona tu proyecto.
  2. Ve a la pestaña Authentication desde el menú lateral izquierdo.
  3. Haz clic en Configurar método de acceso y habilita el método de Correo electrónico y contraseña.
  4. En la pestaña de usuarios, haz clic en Añadir usuario. Introduce un correo electrónico y contraseña para crear un usuario de prueba.

Implementar Login

En primer lugar vamos a configurar la función de login en nuestro archivo de configuración de firebase.

// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth, signInWithEmailAndPassword } from "firebase/auth";


// Your web app's Firebase configuration
const firebaseConfig = {
  apiKey: "TU_API_KEY",
  authDomain: "TU_AUTH_DOMAIN",
  projectId: "TU_PROJECT_ID",
  storageBucket: "TU_STORAGE_BUCKET",
  messagingSenderId: "TU_MESSAGING_SENDER_ID",
  appId: "TU_APP_ID",
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);

// Login function
export const login = ({email, password}) => {
  return signInWithEmailAndPassword(auth, email, password)
} 

Implementamos el formulario de Login.jsx para manejar el inicio de sesión:

import { useState } from "react";
import { login } from "../config/firebase";

const Login = () => {
  const [email, setEmail] = useState("test@test.com");
  const [password, setPassword] = useState("123456");


  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      await login({ email, password });
      console.log("user logged in");
    } catch (error) {
      console.log(error.code);
      console.log(error.message);
    }
  };

  return (
    <>
      <h1>Login</h1>
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          placeholder="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
        />
        <input
          type="password"
          placeholder="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
        />
        <button type="submit">Login</button>
      </form>
    </>
  );
};

export default Login;

Implementar Registro

Configuramos la función de registro en nuestro archivo de configuración de firebase.

// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth, signInWithEmailAndPassword, createUserWithEmailAndPassword } from "firebase/auth";


// Your web app's Firebase configuration
const firebaseConfig = {
  apiKey: "TU_API_KEY",
  authDomain: "TU_AUTH_DOMAIN",
  projectId: "TU_PROJECT_ID",
  storageBucket: "TU_STORAGE_BUCKET",
  messagingSenderId: "TU_MESSAGING_SENDER_ID",
  appId: "TU_APP_ID",
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);

// Login function
export const login = ({email, password}) => {
  return signInWithEmailAndPassword(auth, email, password)
} 

// Register function
export const register = ({email, password}) => {
  return createUserWithEmailAndPassword(auth, email, password)
}

Implementamos el formulario de Registro.jsx para manejar el registro de nuevos usuarios:

import React, { useState } from 'react'
import { register } from '../config/Firebase'

const Registro = () => {
  const [email, setEmail] = useState("test@test.com")
  const [password, setPassword] = useState("123456")

  const handleSubmit = async (e) => {
    e.preventDefault()
    try {
      await register({email, password})
      console.log("User logged in")
    } catch (error) {
      console.log(error.code)
      console.log(error.message)
    }
  }

  return (
    <div>
      <h1>Registro</h1>

      <form onSubmit={handleSubmit}>
        <input 
          type="text" 
          placeholder='email'
          value={email}
          onChange={(e)=>{setEmail(e.target.value)}}
        />
      <input 
          type="password" 
          placeholder='password'
          value={password}
          onChange={(e)=>{setPassword(e.target.value)}}
        />
      <button type='submit'>Registrar</button>
      </form>
    </div>
  )
}

export default Registro

Observador para detectar usuarios logueados

Configuramos un observador en el componente UserContext.jsx, para verificar si hay un usuario autenticado.

import React, { createContext, useEffect, useState } from 'react'
import { auth } from '../config/Firebase'
import { onAuthStateChanged } from 'firebase/auth'

export const UserContext = createContext()


const UserProvider = ({children}) => {
  const [user, setUser] = useState(false)

  useEffect(()=> {
   const unsuscribe = onAuthStateChanged(auth, (user) => {
      if (user) {
        setUser(user)
     } else {
      }
      return unsuscribe
    });

  }, []) 

  if (user===null) return <p>Loading...</p>

  return (
    <UserContext.Provider value ={{user, setUser}}>
        {children}
    </UserContext.Provider>
  )
}

export default UserProvider

Modificamos el componente Login.jsx para que, cuando un usuario se loguee, lo redirija al panel privado, Dashboard.jsx.

import React, { useContext, useEffect, useState } from 'react'
import { login } from '../config/Firebase'
import { useNavigate } from 'react-router-dom'
import { UserContext } from '../context/UserContext'

const Login = () => {
  const [email, setEmail] = useState("test@test.com")
  const [password, setPassword] = useState("123456")

  const {user} = useContext(UserContext)
  const navigate = useNavigate()

  useEffect(()=> {
    if (user) navigate("/dashboard")
  }, [user])

  const handleSubmit = async (e) => {
    e.preventDefault()
    try {
      await login({email, password})
      console.log("User logged in")
    } catch (error) {
      console.log(error.code)
      console.log(error.message)
    }
  }

  return (
    <div>
      <h1>Login</h1>

      <form onSubmit={handleSubmit}>
        <input 
          type="text" 
          placeholder='email'
          value={email}
          onChange={(e)=>{setEmail(e.target.value)}}
        />
      <input 
          type="password" 
          placeholder='password'
          value={password}
          onChange={(e)=>{setPassword(e.target.value)}}
        />
      <button type='submit'>Login</button>
      </form>
    </div>
  )
}

export default Login

Modificamos el componente Register.jsx para que, cuando un usuario se registre exitosamente, sea redirigido al panel privado, Dashboard.jsx.

import React, { useContext, useEffect, useState } from 'react'
import { register } from '../config/Firebase'
import { useNavigate } from 'react-router-dom'
import { UserContext } from '../context/UserContext'

const Registro = () => {
  const [email, setEmail] = useState("test@test.com")
  const [password, setPassword] = useState("123456")

  const {user} = useContext(UserContext)
  const navigate = useNavigate()

  useEffect(()=> {
    if (user) navigate("/dashboard")
  }, [user])


  const handleSubmit = async (e) => {
    e.preventDefault()
    try {
      await register({email, password})
      console.log("User logged in")
    } catch (error) {
      console.log(error.code)
      console.log(error.message)
    }
  }

  return (
    <div>
      <h1>Registro</h1>

      <form onSubmit={handleSubmit}>
        <input 
          type="text" 
          placeholder='email'
          value={email}
          onChange={(e)=>{setEmail(e.target.value)}}
        />
      <input 
          type="password" 
          placeholder='password'
          value={password}
          onChange={(e)=>{setPassword(e.target.value)}}
        />
      <button type='submit'>Registrar</button>
      </form>
    </div>
  )
}

export default Registro

Implementar Cerrar Sesión

Añadimos la función para cerrar sesión en el archivo de configuración de firebase, Firebase.jsx.

// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth, signInWithEmailAndPassword, createUserWithEmailAndPassword, signOut } from "firebase/auth";


// Your web app's Firebase configuration
const firebaseConfig = {
  apiKey: "TU_API_KEY",
  authDomain: "TU_AUTH_DOMAIN",
  projectId: "TU_PROJECT_ID",
  storageBucket: "TU_STORAGE_BUCKET",
  messagingSenderId: "TU_MESSAGING_SENDER_ID",
  appId: "TU_APP_ID",
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);

// Login function
export const login = ({email, password}) => {
  return signInWithEmailAndPassword(auth, email, password)
} 

// Register function
export const register = ({email, password}) => {
  return createUserWithEmailAndPassword(auth, email, password)
}

// LogOut function
export const logOut = () => signOut(auth);

Implementamos el botón cerrar sesión en el Nabvar.jsx:

import { useContext } from "react";
import { NavLink, useNavigate } from "react-router-dom";
import { UserContext } from "../context/UserContext";
import { logOut } from "../config/firebase";

const Navbar = () => {
    const {user, setUser} = useContext(UserContext)

    const handleLogout = async () => {
        await logOut();
        setUser(false)
      };

    return (
            <nav>
                <NavLink to="/">Home |</NavLink>
                <NavLink to="/dashboard">  Dashboard |</NavLink>
                <NavLink to="/login">  LogIn |</NavLink>
                <NavLink to="/registro">  Register  |</NavLink>
                <NavLink onClick={handleLogout}>  Cerrar sesión</NavLink>
            </nav>
    );
};

export default Navbar;

Arreglar el Navbar según el estado del usuario

Actualizamos el Navbar.jsx para mostrar enlaces diferentes dependiendo de si el usuario está autenticado.

import { useContext } from "react";
import { NavLink, useNavigate } from "react-router-dom";
import { UserContext } from "../context/UserContext";
import { logOut } from "../config/firebase";

const Navbar = () => {
    const {user, setUser} = useContext(UserContext)

    const handleLogout = async () => {
        await logOut();
        setUser(false)
      };

    return (
            <nav>
                <NavLink to="/">Home |</NavLink>
                {user && <NavLink to="/dashboard">  Dashboard |</NavLink>}
                {
                    user ? (
                        <NavLink onClick={handleLogout}>  Cerrar sesión |</NavLink>
                    ) : (
                        <>
                            <NavLink to="/login">  LogIn |</NavLink>
                            <NavLink to="/register">  Register</NavLink>
                        </>
                    )
                }
            </nav>

    );
};

export default Navbar;

Con esto ya tenemos implementado un sistema de autenticación funcional con Firebase en React.