Saltar al contenido

Lección 11 de 12 · Lectura y práctica

ErrorBoundary React: ejemplo práctico y fallback

Imagina que estás construyendo una aplicación React compleja con múltiples componentes anidados. De repente, un pequeño componente en lo más profundo de tu árbol de componentes lanza un error inesperado. Sin los conocimientos.

Del concepto a la práctica

Taller de esta lección

Una Error Boundary debe aislar una zona de render que puede fallar y ofrecer una recuperación comprensible. No sustituye el manejo de errores de eventos o de operaciones asíncronas. El límite debe rodear la sección independiente, no ocultar indiscriminadamente toda la aplicación.

Ejemplo resuelto

jsx
class SectionBoundary extends React.Component {
  state = {failed:false};
  static getDerivedStateFromError() { return {failed:true}; }
  render() { return this.state.failed ? <p role="alert">Métricas no disponibles</p> : this.props.children; }
}

Si el hijo lanza durante render, aparece exactamente el mensaje del fallback.

Pruébalo

  1. Envuelve solo el panel de métricas.

  2. Usa un hijo que lance al renderizar.

  3. Verifica que la lista de pedidos continúa visible junto al role="alert".

Comprueba tu resultado

Error frecuente: envolver el propio fallback con el mismo límite defectuoso. Corrígelo manteniendo el fallback simple.

Ejercicio: corrige el lanzamiento y remonta SectionBoundary con una key distinta; el resultado esperado es contenido normal y ningún mensaje de alerta.

SectionBoundary conserva failed=true tras el fallo de métricas. Para la segunda prueba, corrige el hijo y cambia la key del límite para montar una instancia limpia; sin ese paso el fallback permanece aunque el dato haya cambiado. Mantén el mensaje de alerta simple: si su propio render falla, el error debe subir a otro límite.

Tres filas separan error durante render, capturado por Boundary con interfaz alternativa, error de clic manejado con try/catch y promesa fetchData rechazada manejada con catch.
CursaloMapa de práctica
Qué captura una Error Boundary

Una Error Boundary situada sobre el componente captura errores que se lanzan durante su render y muestra una interfaz alternativa. Un handler de clic y una promesa ordinaria como fetchData requieren manejo explícito en su propio código. Un import de lazy rechazado constituye otro caso: React lanza ese error durante el render al boundary más cercano.

Ver la infografía en tamaño completo ↗
Fuentes para profundizar

Imagina que estás construyendo una aplicación React compleja con múltiples componentes anidados. De repente, un pequeño componente en lo más profundo de tu árbol de componentes lanza un error inesperado. Sin los conocimientos adecuados, toda tu aplicación podría colapsar, mostrando una pantalla en blanco al usuario. ¿Te suena familiar?

Los Error Boundaries son el mecanismo elegante que React nos proporciona para evitar exactamente este escenario. En esta lección, aprenderás cómo implementarlos correctamente y cuándo utilizarlos para crear aplicaciones más robustas y profesionales.


CONCEPTO CLAVE

Un Error Boundary es un componente React de clase que implementa los métodos del ciclo de vida static getDerivedStateFromError() o componentDidCatch(). Su único propósito es detectar errores JavaScript en cualquier parte del árbol de componentes y renderizar una interfaz de fallback en lugar de dejar que toda la aplicación se caiga.

Los Error Boundaries actúan como contenedores de errores que interceptan excepciones no controladas antes de que se propaguen y rompan toda la aplicación.


¿Por Qué Necesitamos Error Boundaries?

Respuesta rápida: ErrorBoundary en React: Un ErrorBoundary en React es un componente de clase que captura errores de renderizado en sus componentes hijos, muestra una UI de fallback y permite registrar el error con componentDidCatch. Normalmente combina static getDerivedStateFromError para actualizar estado y componentDidCatch para logging.

En JavaScript tradicional, los errores en una parte del código pueden afectar a toda la ejecución. En React, esto es especialmente crítico porque los componentes están organizados en un árbol jerárquico. Cuando un componente lanza un error no manejado:

  • React elimina todo el árbol de componentes del DOM
  • La aplicación muestra una pantalla en blanco o un error críptico
  • El estado interno se corrompe de forma irreversible
  • La experiencia del usuario se degrada completamente
"Los errores en producción son inevitables. Lo que distingue una aplicación profesional es cómo manejas esos errores cuando ocurren."

Los Error Boundaries resuelven este problema permitiendo que nuestra aplicación se recupere gracefully de errores inesperados, mostrando contenido alternativo y manteniendo el resto de la aplicación funcionando.


Implementando tu Primer Error Boundary

Paso 1: Crear el Componente Error Boundary

  1. Crear un componente de clase que extienda de React.Component
  2. Implementar componentDidCatch() para capturar el error y actualizar el estado
  3. Implementar static getDerivedStateFromError() para renderizar la UI de fallback
  4. Usar el componente envolviendo otros componentes que queramos proteger

Ejemplo Práctico Completo:

// ErrorBoundary.jsx
import React, { Component } from 'react';

class ErrorBoundary extends Component {
  constructor(props) {
    super(props);
    this.state = {
      hasError: false,
      error: null,
      errorInfo: null
    };
  }

  static getDerivedStateFromError(error) {
    // Se llama durante la fase de renderizado
    // Actualiza el estado para mostrar la UI de fallback
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // Se llama después de que ocurre el error
    // Útil para logging y reportes de errores
    console.error('ErrorBoundary capturó un error:', error);
    console.error('Información del componente:', errorInfo);
    
    // Enviar a servicios de monitoreo como Sentry
    // logErrorToMyService(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return (
        <div className="error-fallback">
          <h2>😔 Algo salió mal</h2>
          <p>{this.state.error?.toString()}</p>
          <button onClick={() => window.location.reload()}>
            Recargar Página
          </button>
        </div>
      );
    }

    return this.props.children;
  }
}

export default ErrorBoundary;

Paso 2: Usar el Error Boundary

// App.jsx
import React from 'react';
import ErrorBoundary from './ErrorBoundary';
import WidgetClimatico from './components/WidgetClimatico';
import PerfilUsuario from './components/PerfilUsuario';
import PanelAdmin from './components/PanelAdmin';

function App() {
  return (
    <div className="app">
      <header>
        <h1>Mi Aplicación</h1>
      </header>
      
      <ErrorBoundary>
        <WidgetClimatico />
      </ErrorBoundary>
      
      <ErrorBoundary>
        <PerfilUsuario />
      </ErrorBoundary>
      
      <ErrorBoundary>
        <PanelAdmin />
      </ErrorBoundary>
    </div>
  );
}

export default App;
💡 Consejo profesional: Coloca los Error Boundaries estratégicamente. Puedes envolver componentes individuales (para aislamiento granular) o secciones enteras de tu aplicación. La decisión depende del balance entre granularidad y complejidad.

Limitaciones de los Error Boundaries

⚠️ IMPORTANTE: Los Error Boundaries NO capturan errores en las siguientes situaciones:
Escenario ¿Se captura? Alternativa
Eventos (onClick, onChange) ❌ No try/catch manual
Código asíncrono (setTimeout, promises) ❌ No try/catch o .catch() en promesas
Renderizado en el servidor (SSR) ❌ No Manejo a nivel de servidor
El Error Boundary mismo ❌ No Nested Error Boundaries
Los Error Boundaries solo interceptan errores que ocurren durante el renderizado, métodos del ciclo de vida, y constructores de los componentes hijos. No funcionan en callbacks de eventos ni código asíncrono.

Patrones Avanzados de Error Boundaries

Error Boundary con Funcionalidad de Retry

class RetryableErrorBoundary extends Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false, error: null };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }

  resetError = () => {
    this.setState({ hasError: false, error: null });
  };

  render() {
    if (this.state.hasError) {
      return (
        <div className="fallback-container">
          <h3>Error en el componente</h3>
          <p>{this.state.error?.message}</p>
          {this.props.onReset?.(this.resetError)}
          <button onClick={this.resetError}>
            Reintentar
          </button>
        </div>
      );
    }
    return this.props.children;
  }
}

Error Boundary con Diferentes UI según el Error

class AdaptiveErrorBoundary extends Component {
  state = { hasError: false, error: null };

  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }

  getFallbackUI(error) {
    if (error.status === 404) {
      return <ComponenteNoEncontrado />;
    }
    if (error.status === 401) {
      return <PaginaNoAutorizado />;
    }
    if (error instanceof NetworkError) {
      return <SinConexion />;
    }
    return <ErrorGenerico />;
  }

  render() {
    if (this.state.hasError) {
      return this.getFallbackUI(this.state.error);
    }
    return this.props.children;
  }
}

Integración con Servicios de Monitoreo

Los Error Boundaries son el lugar perfecto para integrar herramientas de monitoreo de errores como Sentry, Bugsnag o LogRocket:

componentDidCatch(error, errorInfo) {
  // Integración con Sentry
  Sentry.captureException(error, { extra: errorInfo });
  
  // Integración con LogRocket
  LogRocket.captureException(error, {
    tags: { component: errorInfo.componentStack },
    extra: { errorInfo }
  });
  
  // Logging personalizado
  console.error('Error capturado:', {
    mensaje: error.message,
    stack: error.stack,
    componente: errorInfo.componentStack,
    timestamp: new Date().toISOString()
  });
}
📌 Recuerda: El logging de errores es tan importante como el manejo visual. Sin información adecuada, debuggear errores en producción se convierte en una pesadilla. Integra tu Error Boundary con herramientas de monitoreo desde el inicio.

Buenas Prácticas

Práctica Descripción
No sobredimensionar Un solo Error Boundary para toda la app pierde granularidad
No subdimensionar Error Boundary en cada componente genera código repetitivo
UI de fallback amigable No muestres el error técnico, ofrece acciones al usuario
Combinar con try/catch Para eventos y código asíncrono, usa try/catch tradicional
Mantener estado limpio El error puede dejar estado inconsistente; considera un "reset"
💡 Patrón recomendado: Utiliza un Error Boundary a nivel de ruta (para toda una sección) y otro más granular para componentes críticos individuales como widgets o formularios principales.

Ejemplo Real: Protegiendo una Aplicación de Dashboard

// DashboardLayout.jsx
import React from 'react';
import ErrorBoundary from '../components/ErrorBoundary';
import GraficosVentas from './GraficosVentas';
import ListaClientes from './ListaClientes';
import NotificacionesPanel from './NotificacionesPanel';

function DashboardLayout() {
  return (
    <div className="dashboard">
      <aside>
        <ErrorBoundary fallback={<MenuFallback />}>
          <MenuNavegacion />
        </ErrorBoundary>
      </aside>
      
      <main>
        <ErrorBoundary fallback={<ErrorGraficos />}>
          <GraficosVentas />
        </ErrorBoundary>
        
        <ErrorBoundary fallback={<ErrorLista />}>
          <ListaClientes />
        </ErrorBoundary>
      </main>
      
      <aside>
        <ErrorBoundary fallback={<NotificacionesError />}>
          <NotificacionesPanel />
        </ErrorBoundary>
      </aside>
    </div>
  );
}

export default DashboardLayout;
Ver más: Versión con componente de clase completo
class DashboardErrorBoundary extends Component {
  constructor(props) {
    super(props);
    this.state = { error: null };
  }

  static getDerivedStateFromError(error) {
    return { error };
  }

  componentDidCatch(error, info) {
    // Registrar en servicio de análisis
    analytics.track('component_error', {
      error: error.message,
      component: this.props.nombreComponente,
      timestamp: Date.now()
    });
  }

  render() {
    if (this.state.error) {
      if (this.props.fallback) {
        return this.props.fallback;
      }
      return (
        <div className="error-boundary-fallback">
          <h4>⚠️ Error en {this.props.nombreComponente}</h4>
          <p>Este componente encontró un problema.</p>
          <button onClick={() => this.setState({ error: null })}>
            Reintentar
          </button>
        </div>
      );
    }
    return this.props.children;
  }
}

export default DashboardErrorBoundary;

🧠 Quiz: Error Boundaries

¿Cuál de las siguientes situaciones SÍ sería capturada por un Error Boundary?

  • A) Un error en un callback onClick
  • B) Un error durante el renderizado de un componente hijo
  • C) Un error dentro de un setTimeout
  • D) Un error en una promesa no manejada
✅ Respuesta correcta: B
Los Error Boundaries capturan errores durante el renderizado, constructores y métodos del ciclo de vida de los componentes hijos. Para las opciones A, C y D, necesitas usar try/catch tradicionales o el método .catch() de las promesas.

🧠 Quiz: Implementación

¿Qué método del ciclo de vida se utiliza para actualizar el estado cuando ocurre un error y debe usarse para renderizar la UI de fallback?

  • A) componentDidCatch
  • B) componentDidUpdate
  • C) static getDerivedStateFromError
  • D) componentWillUnmount
✅ Respuesta correcta: C
static getDerivedStateFromError() es el método correcto porque se llama durante la fase de renderizado y permite actualizar el estado antes de que React intente renderizar nuevamente. componentDidCatch() se usa para efectos secundarios como logging, no para actualizar el estado de renderizado.

Conclusión

Los Error Boundaries son una herramienta fundamental en el arsenal de cualquier desarrollador React profesional. No solo protegen tu aplicación de fallos inesperados, sino que también mejoran significativamente la experiencia del usuario al proporcionar interfaces de recuperación elegantes.

CONCEPTO CLAVE

Recuerda los puntos esenciales:

  • Los Error Boundaries son componentes de clase que implementan getDerivedStateFromError() o componentDidCatch()
  • Solo capturan errores de renderizado y ciclo de vida, no de eventos o código asíncrono
  • Úsalos estratégicamente para balancear granularidad y mantenibilidad
  • Combínalos con try/catch para cobertura completa de errores
  • Integralos con servicios de monitoreo para mejor debugging

En la próxima lección, exploraremos patrones adicionales de manejo de errores en React y cómo combinarlos con técnicas de testing para asegurar aplicaciones más robustas. ¡Sigue practicando!

Ejemplo moderno de ErrorBoundary

React mantiene los Error Boundaries como una responsabilidad de componentes de clase. Podés usarlos dentro de una app con componentes funcionales envolviendo secciones sensibles como dashboards, widgets, formularios complejos o paneles de terceros.

import React from "react";

type Props = { children: React.ReactNode };
type State = { hasError: boolean };

export class ErrorBoundary extends React.Component<Props, State> {
  state: State = { hasError: false };

  static getDerivedStateFromError() {
    return { hasError: true };
  }

  componentDidCatch(error: Error, info: React.ErrorInfo) {
    console.error("Error capturado por ErrorBoundary", error, info.componentStack);
  }

  render() {
    if (this.state.hasError) {
      return <section role="alert">No pudimos cargar esta sección.</section>;
    }

    return this.props.children;
  }
}

Qué errores no captura

  • Errores dentro de event handlers, donde conviene usar try/catch.
  • Errores asíncronos fuera del render, como setTimeout o callbacks externos.
  • Errores del propio ErrorBoundary.
  • Errores del servidor si estás renderizando fuera del cliente.

Referencia oficial: React docs sobre Error Boundaries.

Checklist para implementar un ErrorBoundary sin romper UX

  • Ubicalo alrededor de zonas críticas: dashboards, widgets externos, editores, reportes o pantallas con mucha lógica.
  • No lo uses para event handlers: esos errores se manejan con try/catch dentro del evento.
  • Mostrá una UI de fallback útil: explicá qué pasó y ofrecé reintentar, volver o contactar soporte.
  • Registrá el error: usá componentDidCatch(error, info) para enviar el stack a Sentry, logs internos o tu backend.
  • Probalo manualmente: creá un componente que lance un error y verificá que no caiga toda la app.

De ErrorBoundary a habilidad laboral

Saber explicar un ErrorBoundary en React sirve para entrevistas frontend porque demuestra criterio de resiliencia, no solo sintaxis. Convertí esta lección en evidencia agregando a tu portfolio una pantalla que falla de forma controlada, muestra fallback UI y registra el error.

Conectá esta habilidad con la ruta de Desarrollador Frontend, revisá rutas de empleo y ofrecé servicios de auditoría React, manejo de errores o hardening de interfaces desde el marketplace de profesionales.

ErrorBoundary vs try/catch en React

Un ErrorBoundary no es un reemplazo general de try/catch. React lo usa para errores que aparecen durante el renderizado de componentes hijos. En cambio, try/catch sigue siendo útil en eventos, promesas, llamadas a APIs o funciones que ejecutás manualmente.

CasoQué usarMotivo
Un componente hijo falla mientras renderiza.ErrorBoundaryReact propaga el fallo por el árbol y muestra fallback UI.
Click en un botón ejecuta código que puede fallar.try/catchLos Error Boundaries no capturan event handlers.
Una promesa o callback asíncrono falla.Manejo de promesas + estado de error.El error no ocurre durante el render síncrono del hijo.
Querés evitar escribir la clase manualmente.react-error-boundaryReact no tiene equivalente directo como función; esta librería abstrae el patrón.

Referencia oficial: la documentación de React indica que los Error Boundaries no capturan event handlers, SSR, errores asíncronos ni errores del propio boundary. El lint oficial también advierte que un try/catch alrededor de JSX no captura errores de render de hijos.

Sigue con React Intermedio: Patrones y Optimización

Esta lección forma parte de un curso de Cursalo. Revisa su programa y elige entre la compra individual o el acceso a toda la escuela.

Si ya tenías acceso a este curso, entra con tu cuenta: tus derechos y tu progreso se conservan. No necesitas comprarlo de nuevo.

01 / ELEGIR UNA RUTA

El próximo paso

Aprende IA mientras construyes algo que sí necesitas.

Empieza por el curso inicial o explora el catálogo para encontrar una práctica alineada con tu trabajo.