Fondo abstracto con título y logo de React

En el desarrollo con React, uno de los desafíos comunes es compartir estados entre componentes sin caer en el props drilling (pasar props a través de múltiples niveles de componentes). React Context ofrece una solución elegante para este problema, permitiéndonos crear un estado global accesible desde cualquier parte de nuestra aplicación.

Artículo sobre el estado global y  props drilling. 

En este artículo, exploraremos cómo implementar una autenticación usando React Context, siguiendo un ejemplo práctico sencillo.

¿Por qué usar Context para autenticación?

La autenticación es un candidato perfecto para Context porque:

  1. Es un estado global: Muchos componentes necesitan saber si el usuario está autenticado

  2. Requiere acciones compartidas: Login y logout se necesitan en diferentes partes de la app

  3. Evita repetición de código: No necesitas pasar props a través de toda la jerarquía

Implementación paso a paso

1. Creando el Contexto de Autenticación

Creamos un archivo AuthContext.tsx que contendrá nuestra lógica de autenticación:

 
import { createContext, useContext, useState, ReactNode } from "react";

type AuthContextType = {
  isAuthenticated: boolean;
  login: () => void;
  logout: () => void;
};

const AuthContext = createContext<AuthContextType | undefined>(undefined);

export const AuthProvider = ({ children }: { children: ReactNode }) => {
  const [isAuthenticated, setIsAuthenticated] = useState(false);

  const login = () => setIsAuthenticated(true);
  const logout = () => setIsAuthenticated(false);

  return (
    <AuthContext.Provider value={{ isAuthenticated, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error("useAuth debe usarse dentro de AuthProvider");
  }
  return context;
};
  • Definimos un tipo AuthContextType para TypeScript

  • Creamos el contexto con createContext

  • AuthProvider es el componente que envuelve nuestra app y provee el estado

  • useAuth es un hook personalizado para acceder fácilmente al contexto

2. Configurando el Provider en la aplicación

En main.tsx envolvemos nuestra app con el AuthProvider:

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
import { AuthProvider } from './context/AuthContext'

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <AuthProvider>
      <App />
    </AuthProvider>
  </React.StrictMode>,
)

3. Creando componentes que usan el contexto

Navbar.tsx - Muestra estado de autenticación y botón de logout:

import { useAuth } from "../context/AuthContext";

export default function Navbar() {
  const { isAuthenticated, logout } = useAuth();

  return (
    <nav>
      {isAuthenticated ? (
        <>
          <span>Estás autenticado</span>
          <button onClick={logout}>Cerrar sesión</button>
        </>
      ) : (
        <span>No has iniciado sesión</span>
      )}
    </nav>
  );
}

Login.tsx - Componente con botón de login:

import { useAuth } from "../context/AuthContext";

export default function Login() {
  const { isAuthenticated, login } = useAuth();

  if (isAuthenticated) return <p>Ya estás autenticado</p>;

  return <button onClick={login}>Iniciar sesión</button>;
}

Home.tsx - Muestra contenido condicional:

import { useAuth } from "../context/AuthContext";

export default function Home() {
  const { isAuthenticated } = useAuth();

  return (
    <div>
      {isAuthenticated ? (
        <h1>Bienvenido a tu panel</h1>
      ) : (
        <p>Por favor inicia sesión para ver el contenido</p>
      )}
    </div>
  );
}

4. Ensamblando todo en App.tsx

import Navbar from "./components/Navbar";
import Login from "./components/Login";
import Home from "./components/Home";

function App() {
  return (
    <>
      <Navbar />
      <Login />
      <Home />
    </>
  );
}

export default App;

Flujo de autenticación

  1. Estado inicialisAuthenticated = false

  2. Usuario no autenticado:

    • Navbar muestra "No has iniciado sesión"

    • Login muestra botón "Iniciar sesión"

    • Home muestra mensaje para iniciar sesión

  3. Al hacer clic en "Iniciar sesión":

    • login() cambia isAuthenticated a true

    • Todos los componentes se actualizan:

      • Navbar ahora muestra estado autenticado y botón de logout

      • Login muestra "Ya estás autenticado"

      • Home muestra el contenido protegido

Beneficios de esta implementación

  1. Centralización del estado: Toda la lógica de autenticación en un solo lugar

  2. Reutilización: Cualquier componente puede acceder al estado con useAuth()

  3. Mantenibilidad: Cambios en la lógica de autenticación solo afectan el contexto

  4. Escalabilidad: Fácil de extender con más funcionalidades (user data, tokens, etc.)

React Context es una herramienta que permite manejar estados globales como la autenticación. Este ejemplo muestra como funciona la lógica, evitando el props drilling.

Code In Progress with ❤️ by Juan Pablo Amador