Advanced

Disenando Error Boundaries con Claude Code: Del Frontend a la API

Disenando Error Boundaries usando Claude Code. Del Frontend a la API. Incluye ejemplos practicos de codigo.

Que son los Error Boundaries

Los error boundaries son un patron de diseno defensivo que evita que toda la aplicacion se bloquee cuando ocurre un error en una parte. Con Claude Code, puede disenar un manejo de errores consistente tanto en el frontend como en el backend.

React Error Boundary

import { Component, ErrorInfo, ReactNode } from "react";

interface ErrorBoundaryProps {
  children: ReactNode;
  fallback?: ReactNode;
  onError?: (error: Error, errorInfo: ErrorInfo) => void;
}

interface ErrorBoundaryState {
  hasError: boolean;
  error: Error | null;
}

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

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

  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    console.error("Error capturado por el boundary:", error, errorInfo);
    this.props.onError?.(error, errorInfo);

    // Enviar al servicio de monitoreo de errores
    reportError(error, {
      componentStack: errorInfo.componentStack,
    });
  }

  render() {
    if (this.state.hasError) {
      return (
        this.props.fallback || (
          <div className="error-fallback">
            <h2>Ha ocurrido un error</h2>
            <p>{this.state.error?.message}</p>
            <button onClick={() => this.setState({ hasError: false, error: null })}>
              Reintentar
            </button>
          </div>
        )
      );
    }

    return this.props.children;
  }
}

Hook para componentes funcionales

import { useCallback, useState } from "react";

function useErrorHandler() {
  const [error, setError] = useState<Error | null>(null);

  if (error) {
    throw error; // Capturado por el Error Boundary padre
  }

  const handleError = useCallback((err: unknown) => {
    if (err instanceof Error) {
      setError(err);
    } else {
      setError(new Error(String(err)));
    }
  }, []);

  const withErrorHandling = useCallback(
    <T,>(fn: () => Promise<T>) => {
      return async () => {
        try {
          return await fn();
        } catch (err) {
          handleError(err);
          return undefined;
        }
      };
    },
    [handleError]
  );

  return { handleError, withErrorHandling };
}

Estandarizacion de respuestas de error de API

// Definicion de codigos de error
enum ErrorCode {
  VALIDATION_ERROR = "VALIDATION_ERROR",
  NOT_FOUND = "NOT_FOUND",
  UNAUTHORIZED = "UNAUTHORIZED",
  FORBIDDEN = "FORBIDDEN",
  CONFLICT = "CONFLICT",
  INTERNAL_ERROR = "INTERNAL_ERROR",
  RATE_LIMITED = "RATE_LIMITED",
}

interface ApiError {
  code: ErrorCode;
  message: string;
  details?: Record<string, unknown>;
  requestId: string;
  timestamp: string;
}

class AppError extends Error {
  constructor(
    public code: ErrorCode,
    message: string,
    public statusCode: number,
    public details?: Record<string, unknown>
  ) {
    super(message);
    this.name = "AppError";
  }

  static notFound(resource: string) {
    return new AppError(
      ErrorCode.NOT_FOUND,
      `${resource} not found`,
      404
    );
  }

  static validation(details: Record<string, string>) {
    return new AppError(
      ErrorCode.VALIDATION_ERROR,
      "Validation failed",
      400,
      details
    );
  }

  static unauthorized(message = "Authentication required") {
    return new AppError(ErrorCode.UNAUTHORIZED, message, 401);
  }
}

Manejador de errores global

import { v4 as uuidv4 } from "uuid";

function globalErrorHandler(
  err: Error,
  req: express.Request,
  res: express.Response,
  next: express.NextFunction
) {
  const requestId = uuidv4();

  if (err instanceof AppError) {
    // Error de negocio
    return res.status(err.statusCode).json({
      code: err.code,
      message: err.message,
      details: err.details,
      requestId,
      timestamp: new Date().toISOString(),
    });
  }

  // Error inesperado
  console.error(`[${requestId}] Unexpected error:`, err);

  res.status(500).json({
    code: ErrorCode.INTERNAL_ERROR,
    message: "An unexpected error occurred",
    requestId,
    timestamp: new Date().toISOString(),
  });
}

// El orden de registro es importante: colocar despues de los routers
app.use(globalErrorHandler);

Captura de errores asincronos

// Wrapper asyncHandler
function asyncHandler(
  fn: (
    req: express.Request,
    res: express.Response,
    next: express.NextFunction
  ) => Promise<void>
) {
  return (
    req: express.Request,
    res: express.Response,
    next: express.NextFunction
  ) => {
    Promise.resolve(fn(req, res, next)).catch(next);
  };
}

// Ejemplo de uso
router.get(
  "/users/:id",
  asyncHandler(async (req, res) => {
    const user = await prisma.user.findUnique({
      where: { id: req.params.id },
    });

    if (!user) {
      throw AppError.notFound("User");
    }

    res.json({ data: user });
  })
);

Error Boundaries jerarquicos

En el lado de React, se colocan multiples Error Boundaries de forma jerarquica. Use esto como referencia al solicitar el diseno de manejo de errores a Claude Code. Para la redaccion de prompts, consulte 5 tips para prompts efectivos. Para mejorar la calidad del codigo, automatizacion de refactorizacion tambien es util.

function App() {
  return (
    <ErrorBoundary fallback={<FullPageError />}>
      <Header />
      <ErrorBoundary fallback={<SidebarFallback />}>
        <Sidebar />
      </ErrorBoundary>
      <ErrorBoundary fallback={<ContentFallback />}>
        <MainContent />
      </ErrorBoundary>
    </ErrorBoundary>
  );
}

Para los principios de diseno de manejo de errores, MDN Web Docs: Error handling es una buena referencia. Para mas detalles sobre Claude Code, consulte la documentacion oficial.

Resumen

Los error boundaries son un patron de diseno importante para no perjudicar la experiencia del usuario. Con Claude Code, puede implementar eficientemente un manejo de errores consistente desde el frontend hasta la API.

#Claude Code #error handling #React #API design #TypeScript