C
React/Advanced/Lesson 20

Error Boundary — Error Handling

30 min·theory
This chapter
1/2
TypeScript

Error Boundary — Error Handling

💡 Why Should You Learn This?

🎯 Prevents a bug in one component from crashing the entire app.
💼 Users see only a 'Something went wrong' message instead of a full error screen.
Essential in production environments. A stable service means a stronger job candidacy.
🏢 실무에서는
In a banking app, if a bug occurs in the money transfer feature, the entire app turns into a blank white screen without an Error Boundary. With an Error Boundary, only the transfer section shows a 'Temporary error' message, while other features (such as balance inquiry) remain fully usable.

Concept

An Error Boundary is an error-isolation mechanism in React that prevents a single error in the component tree from crashing the entire app, showing a fallback UI instead. In production, it is essential for protecting the user experience and maintaining a stable service.

Why Does It Matter?

In a live production environment, runtime errors caused by third-party library bugs or unexpected data can turn the entire screen into a blank white page. With an Error Boundary in place, only the affected section is replaced with an error UI, allowing users to continue using the rest of the service. Error Boundaries can also be integrated with error-reporting tools to aid in incident detection and debugging.

Core Concept

An Error Boundary works like a firewall in a building. Even if a fire breaks out in one room, the firewall prevents it from spreading to the others. In React, an Error Boundary 'isolates' errors that occur in a specific part of the component tree so the entire app does not go down, and shows users an appropriate fallback UI.

Key Points

  • Can only be implemented in class components (as of React 19)
  • Only catches errors during rendering and in lifecycle methods of child components
  • Does NOT catch errors in event handlers, asynchronous code, or server-side rendering
  • Integrate with error logging for production monitoring
💻 Bad Example — Component Without an Error Boundary
// Dangerous component without error isolation
const UserProfile = () => {
  const [user, setUser] = useState<User | null>(null);
  
  return (
    <div>
      <h1>{user.name}</h1> {/* If user is null, the entire app crashes */}
      <img src={user.avatar} alt="Profile" />
      <ThirdPartyWidget userId={user.id} /> {/* Crashes on third-party error */}
    </div>
  );
};

// App.tsx
const App = () => {
  return (
    <div>
      <Header />
      <UserProfile /> {/* If an error occurs here, the entire screen becomes a white page */}
      <Footer />
    </div>
  );
};
💻 Good Example — Recommended Error Boundary Pattern (2025)
// Modern Error Boundary Class (TypeScript)
interface ErrorBoundaryState {
  hasError: boolean;
  error?: Error;
}

class ErrorBoundary extends Component<
  PropsWithChildren<{ fallback?: ReactNode; onError?: (error: Error) => void }>,
  ErrorBoundaryState
> {
  constructor(props: any) {
    super(props);
    this.state = { hasError: false };
  }

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

  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    // Error logging (Sentry, LogRocket, etc.)
    console.error('Error Boundary caught an error:', error, errorInfo);
    this.props.onError?.(error);
    
    // In production, send to an error reporting service
    if (process.env.NODE_ENV === 'production') {
      // Sentry.captureException(error, { contexts: { errorInfo } });
    }
  }

  render() {
    if (this.state.hasError) {
      return this.props.fallback || (
        <div className="error-fallback">
          <h2>An issue has occurred</h2>
          <p>Please try again shortly.</p>
          <button onClick={() => this.setState({ hasError: false })}>Try again</button>
        </div>
      );
    }

    return this.props.children;
  }
}

// Usage - Strategic placement
const App = () => {
  return (
    <div>
      <Header />
      <ErrorBoundary 
        fallback={<UserProfileError />}
        onError={(error) => analytics.track('user_profile_error', { error: error.message })}
      >
        <UserProfile />
      </ErrorBoundary>
      
      <ErrorBoundary fallback={<div>Unable to load recommended products</div>}>
        <RecommendationSection />
      </ErrorBoundary>
      
      <Footer /> {/* Footer remains visible even if an error occurs */}
    </div>
  );
};
💻 Advanced Example — Using the react-error-boundary Library
// react-error-boundary library commonly used in practice
import { ErrorBoundary, withErrorBoundary } from 'react-error-boundary';

// Custom fallback component
const ErrorFallback = ({ error, resetErrorBoundary }: any) => {
  return (
    <div className="error-boundary-fallback" role="alert">
      <h2>An error occurred</h2>
      <pre style={{ whiteSpace: 'normal' }}>{error.message}</pre>
      <button onClick={resetErrorBoundary}>Try again</button>
    </div>
  );
};

// Wrap component with HOC pattern
const SafeUserDashboard = withErrorBoundary(UserDashboard, {
  FallbackComponent: ErrorFallback,
  onError: (error, errorInfo) => {
    // Error reporting
    logErrorToService(error, errorInfo);
  },
});

// Modern pattern used with React Query
const App = () => {
  return (
    <QueryClientProvider client={queryClient}>
      <ErrorBoundary
        FallbackComponent={ErrorFallback}
        onReset={() => {
          // Invalidate cache on error reset
          queryClient.invalidateQueries();
        }}
        resetKeys={['user']} // Auto-reset if dependencies change
      >
        <UserDashboard />
      </ErrorBoundary>
    </QueryClientProvider>
  );
};

💡 ⚠️ Common Mistakes

  • Placing Error Boundaries only at the very top level, causing the entire page to be replaced with a fallback UI when any error occurs
  • Assuming Error Boundaries will also catch errors in event handlers or asynchronous code (a separate try-catch is required for those)
  • Showing only a fallback UI without any error logging, making it difficult to diagnose problems in production

💡 🎯 Interview Prep

Q: Explain the difference between errors that an Error Boundary can catch and those it cannot.
Q: How would you strategically position Error Boundaries in your application?
Q: What is the difference between an Error Boundary and try-catch?

Hint: Error Boundaries only catch errors during rendering — events and async code require try-catch. Use strategic placement to isolate errors and protect UX. Distinguish the roles of getDerivedStateFromError and componentDidCatch. Emphasize the importance of integrating error reporting and monitoring.

⚛️ React Pattern — Error Boundary Error Handling

Learn step by step, with code, how Error Boundary error handling is used in React.
1 🧩 1. When to Use Error Boundary Error Handling
Situations where this feature is needed.
2 💻 2. Writing the Code
Basic usage of Error Boundary error handling.
3 🎨 3. Rendered Output
What the user sees on screen.
4 💡 4. Production Tips
Common pitfalls and best practices.

🎮 Error Boundary Error Handling — Step-by-Step

Click each step to read its content, then mark it done with the ✓ Understood button to track your progress.
🖥️ Result — rendered React component
✏️ React 코드 수정하기 (클릭해서 열기)
⚛️ React 18 + Babel Standalone — see the result first, then edit the code yourself.

Check Quiz

Which type of error can an Error Boundary NOT catch?
💡 Error Boundaries catch errors during rendering, in lifecycle methods, and in constructors. Errors inside event handlers, asynchronous code (setTimeout, Promise), and SSR are not caught by Error Boundaries.
Error Boundary + Suspense - React