Lesson 22 / 25

Error Boundaries

Contain rendering errors.

Fallback UI for a subtree

If a component throws during rendering, React unmounts the whole tree unless an error boundary catches it. An error boundary is a class component with static getDerivedStateFromError (to show fallback UI) and optionally componentDidCatch (to log the error). Place boundaries around independent areas (a widget, a page section) so one failure does not blank the whole app. Error boundaries do not catch errors in event handlers or async code; handle those with try/catch and state.

One failing widget, one working, run

I ran this with React 19.3 and react-dom 19.3 on Node.js 22, compiling JSX with esbuild 0.28. Browser-style examples use jsdom 29 as a fake DOM (imported from a small setup-dom.mjs file) and act() to apply updates. Two prices are wrapped in separate error boundaries. The one with an amount renders "Rs 499"; the one missing its amount throws, the boundary logs "price missing" and shows "Something went wrong." while the rest of the page keeps working.

import "./setup-dom.mjs";   // test setup: jsdom provides a browser-like DOM in Node
import { Component, act } from "react";
import { createRoot } from "react-dom/client";

class ErrorBoundary extends Component {
  state = { error: null };
  static getDerivedStateFromError(error) { return { error }; }
  componentDidCatch(error) { console.log("logged:", error.message); }
  render() { return this.state.error ? <p>Something went wrong.</p> : this.props.children; }
}
function Price({ amount }) {
  if (amount == null) throw new Error("price missing");
  return <p>Rs {amount}</p>;
}
const origError = console.error; console.error = () => {};      // hide React's dev error report
const root = createRoot(document.getElementById("root"));
await act(() => root.render(<><ErrorBoundary><Price amount={499} /></ErrorBoundary><ErrorBoundary><Price /></ErrorBoundary></>));
console.error = origError;
console.log([...document.querySelectorAll("p")].map(p => p.textContent));

Output:

logged: price missing
[ 'Rs 499', 'Something went wrong.' ]

Report caught errors

Send errors from componentDidCatch to your error-tracking service with context, not just to the console.

Quick check: Which errors do error boundaries catch?

  • Syntax errors in other files
  • Errors in event handlers
  • Network errors in fetch calls by default
  • Errors thrown while rendering components below them
Answer

Errors thrown while rendering components below them — Use try/catch for handlers and async code.