100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
React

Error Boundaries in React

Catch JavaScript errors in a component tree using class-based error boundaries and display a fallback UI instead of crashing.

Performance & TestingIntermediate9 min readJul 8, 2026
Analogies

Introduction

By default, a JavaScript error thrown anywhere in a component's render method, lifecycle method, or constructor unmounts the entire React component tree, resulting in a blank screen. Error boundaries solve this by catching errors in their child component tree, logging them, and displaying a fallback UI instead of crashing the whole application. As of React 18, error boundaries must be implemented as class components — there is no hook equivalent, because the underlying lifecycle methods (getDerivedStateFromError and componentDidCatch) have no hook counterparts.

🏏

Cricket analogy: Normally a fielder collapsing mid-match with injury could force a forfeit; an error boundary is like a reserve-player rule that catches the collapse and substitutes a fallback player instead of forfeiting — but only a class-based captain role can invoke this rule, not a regular player (hooks).

Syntax

jsx
import React from 'react';

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // Update state so the next render shows the fallback UI
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // Log the error to an error reporting service
    console.error('Caught by ErrorBoundary:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return <h2>Something went wrong.</h2>;
    }
    return this.props.children;
  }
}

Explanation

getDerivedStateFromError is a static lifecycle method called during the 'render' phase after a descendant throws; it receives the error and returns a state update, which React uses to re-render with a fallback UI. componentDidCatch is called during the 'commit' phase and is the right place for side effects like logging the error to a service such as Sentry — it receives both the error and componentStack info describing which component threw. An error boundary only catches errors from its children's rendering, lifecycle methods, and constructors — it does NOT catch errors in event handlers, asynchronous code (setTimeout, promises), server-side rendering, or errors thrown in the boundary itself.

🏏

Cricket analogy: getDerivedStateFromError is like the third umpire reviewing a decision during play (render phase) and signaling a fallback ruling; componentDidCatch is like the match referee filing the incident report afterward (commit phase) — but neither catches a spectator's outburst (event handler) or a rain delay (async), only errors from the players (children).

Error boundaries cannot currently be written as function components using hooks — React does not provide a useErrorBoundary or equivalent hook as of React 18, since getDerivedStateFromError and componentDidCatch have no hook-based equivalents. To use error boundaries in a hooks-based codebase, you either write a small dedicated class component (often reused as a wrapper) or use a well-tested community library such as react-error-boundary.

Example

jsx
function BuggyCounter() {
  const [count, setCount] = useState(0);
  if (count === 3) {
    throw new Error('Count reached 3, crashing on purpose!');
  }
  return (
    <button onClick={() => setCount((c) => c + 1)}>
      Count: {count}
    </button>
  );
}

function App() {
  return (
    <ErrorBoundary>
      <BuggyCounter />
    </ErrorBoundary>
  );
}

Output

Clicking the button increments the count normally for 0, 1, and 2. On the third click, count becomes 3, BuggyCounter throws during render, ErrorBoundary catches it via getDerivedStateFromError and componentDidCatch, logs the error to the console, and the UI switches from the button to the fallback message 'Something went wrong.' instead of the whole app crashing to a blank page.

🏏

Cricket analogy: A batter safely completes singles on balls one and two, but on the third ball attempts an ambitious ramp shot and gets bowled; getDerivedStateFromError 'catches' the dismissal, componentDidCatch logs it to the scorebook, and the broadcast switches to a 'Wicket!' graphic instead of the feed cutting out.

Key Takeaways

  • Error boundaries catch JavaScript errors during rendering, in lifecycle methods, and in constructors of their child tree, preventing a full app crash.
  • As of React 18, error boundaries must be class components using getDerivedStateFromError and/or componentDidCatch — there is no hooks equivalent.
  • getDerivedStateFromError updates state to render a fallback UI; componentDidCatch is for side effects like logging.
  • Error boundaries do NOT catch errors in event handlers, async code, or SSR — those need try/catch or other handling.
  • It's common to wrap key parts of an app (e.g., routes or widgets) in separate error boundaries to isolate failures.

Practice what you learned

Was this page helpful?

Topics covered

#React#ReactJsStudyNotes#WebDevelopment#ErrorBoundariesInReact#Error#Boundaries#Syntax#Explanation#StudyNotes#SkillVeris