🚀 ¡Las clases del Bootcamp vuelven el 7 de enero con Node.js! Cargando...

Autenticación y Prop Drilling

Introducción

En esta clase continuamos con el proyecto de React Router. Ya teníamos rutas, lazy load implementado y diferentes páginas funcionando correctamente. Ahora queremos añadir un concepto fundamental en cualquier aplicación: autenticación.

Todavía no vamos a implementar autenticación real. Vamos a simular que el usuario inicia sesión y ver cómo gestionar ese estado en React. Esta clase es clave porque nos llevará directamente al problema del prop drilling, que más adelante resolveremos con Zustand u otros patrones.

Objetivo de la clase

Vamos a:

  • Crear un estado de autenticación en el componente raíz App
  • Pasar ese estado a componentes que lo necesitan (header y página de detalle)
  • Simular login y logout
  • Restringir la acción de “Aplicar a un trabajo” a usuarios autenticados
  • Descubrir los problemas de rendimiento y escalabilidad del prop drilling

Situación inicial del proyecto

El proyecto tiene:

  • React Router configurado
  • Lazy load funcionando (solo se cargan los bundles necesarios por ruta)
  • Varias páginas: Home, Search, Job Detail, NotFound
  • Un Header donde colocaremos el botón de iniciar/cerrar sesión

La clase retoma desde este punto.

Añadiendo el estado de autenticación

El estado de autenticación debe estar en un lugar accesible a toda la app.

Por eso se coloca en App.jsx:

const [isLoggedIn, setIsLoggedIn] = useState(false)

const login = () => setIsLoggedIn(true)
const logout = () => setIsLoggedIn(false)

Ahora queremos que:

  • El Header pueda mostrar “Iniciar sesión” o “Cerrar sesión”
  • El JobDetailPage sepa si el usuario está logueado para permitir o no aplicar a un trabajo

Así que pasamos estas props:

<Header
  isLoggedIn={isLoggedIn}
  onLogin={login}
  onLogout={logout}
/>

<JobDetailPage
  isLoggedIn={isLoggedIn}
/>

Esto funciona perfectamente… pero en cuanto la app crece, empiezan los problemas.

Añadiendo el login en el Header

En Header.jsx:

function Header({ isLoggedIn, onLogin, onLogout }) {
  return (
    <header>
      {isLoggedIn ? (
        <button onClick={onLogout}>Cerrar sesión</button>
      ) : (
        <button onClick={onLogin}>Iniciar sesión</button>
      )}
    </header>
  )
}

Ahora el usuario puede iniciar y cerrar sesión, y el botón cambia automáticamente.

Usando la autenticación en la página de detalle

En JobDetailPage.jsx:

function JobDetailPage({ isLoggedIn }) {
  return (
    <button disabled={!isLoggedIn}>
      {isLoggedIn ? 'Aplicar ahora' : 'Inicia sesión para aplicar'}
    </button>
  )
}

Esto funciona, pero ahora empieza el verdadero problema.

El problema: Prop Drilling

Hasta ahora todo es sencillo: el estado baja un nivel desde App hasta JobDetailPage.

Pero en el vídeo empezamos a dividir JobDetailPage en más componentes:

  • JobDetailHeader
  • JobDetailBreadcrumb
  • JobDetailApplyButton
  • Etc.

Y cada uno de esos niveles necesita recibir isLoggedIn como prop.

Esto provoca que:

App
 └─ JobDetailPage (recibe isLoggedIn)
      └─ JobDetailHeader (recibe isLoggedIn)
           └─ JobDetailApplyButton (recibe isLoggedIn)

A más componentes, más niveles. Y a más niveles, más prop drilling.

Prop drilling consiste en “taladrar” la prop hacia abajo sin que algunos componentes intermedios la necesiten realmente.

Problemas que causa el prop drilling

1. Código difícil de mantener

Para usar una prop en un componente profundo, debes pasarla por todos los de en medio.

2. Acoplamiento innecesario

Componentes que no necesitan isLoggedIn se ven obligados a recibirlo y reenviarlo.

3. Rendimiento pobre

Usando React DevTools (highlight updates), se ve que:

  • Al iniciar o cerrar sesión, gran parte de la app se vuelve a renderizar
  • Incluso componentes que no dependen del estado se actualizan igualmente

Esto sucede porque el estado vive demasiado arriba.

Demostración vista en el vídeo: casi toda la pantalla se ilumina de “updates”.

Intento de solución parcial: Composición

En el vídeo se intenta usar composición para reducir niveles:

<JobDetailPage>
  <JobDetailHeader isLoggedIn={isLoggedIn} />
</JobDetailPage>

Esto ayuda un poco, pero:

  • El estado sigue estando en App
  • Sigue siendo necesario pasarlo por props
  • La propagación hacia abajo continúa

Conclusión: la composición no es suficiente.

Conclusión de la clase

En esta lección hemos visto:

  • ✓ Cómo simular autenticación con estado en React
  • ✓ Cómo pasar login/logout a componentes como el header
  • ✓ Cómo restringir acciones basadas en si el usuario está autenticado
  • ✓ Cómo dividir componentes en subcomponentes más pequeños
  • ✓ Cómo se produce el prop drilling al escalar la UI
  • ✓ Cómo React DevTools permite visualizar renderizados innecesarios
  • ✓ Por qué este patrón no escala y afecta al rendimiento

Esta clase prepara el terreno para introducir una solución mucho mejor:

Estado global con Zustand, evitando prop drilling y re-renderizados innecesarios.

Esto lo veremos en la próxima clase.