
React Error Boundaries Explained

Few things make a React interface feel more fragile than one rendering error taking down an entire section of the page, or worse, the whole application.
Before error boundaries became part of React, a component error could leave the UI in a poor state with very little graceful recovery. Error boundaries improved that by giving us a way to catch rendering errors in part of the tree and replace the broken subtree with fallback UI.
That is the practical value of the feature. It is not about hiding bugs. It is about containing failure.
An Error Boundary Wraps Part of the Tree
If a descendant component throws during rendering, in a lifecycle method, or in its constructor, the boundary can catch that failure and render an alternative interface instead.
This is what the pattern looks like:
type ErrorBoundaryState = { hasError: boolean;};class ErrorBoundary extends React.Component< { children: React.ReactNode }, ErrorBoundaryState> { public state: ErrorBoundaryState = { hasError: false, }; public static getDerivedStateFromError(): ErrorBoundaryState { return { hasError: true, }; } public componentDidCatch(error: Error): void { console.error(error); } public render(): React.ReactNode { if (this.state.hasError) { return <p>Something went wrong in this section.</p>; } return this.props.children; }}That boundary can then wrap a risky or isolated part of the UI.
Using it is usually straightforward:
const ProductPage = (): JSX.Element => { return ( <> <ProductSummary /> <ErrorBoundary> <ReviewsPanel /> </ErrorBoundary> <RelatedProducts /> </> );};That placement matters because it expresses intent clearly. If ReviewsPanel breaks, the review section can fail gracefully without taking the product summary and related products down with it.
Why This Matters in Real Applications
Not every part of a page deserves the same failure behaviour.
If a reviews widget fails, that should not necessarily take down the whole product page. If one dashboard panel breaks, the rest of the dashboard may still be useful.
Error boundaries let us define those containment lines more deliberately.
That improves resilience, but it also improves user trust. A partially degraded interface is often far better than a blank or broken one.
The Fallback UI Should Be Honest
This is easy to overlook.
A good fallback does not pretend the feature worked. It tells the user something went wrong and, where appropriate, offers a next step:
- retry
- refresh
- continue using the rest of the page
- contact support
The exact copy depends on the feature. The important part is honesty. Error boundaries are about graceful failure, not about disguising failure.
componentDidCatch() and getDerivedStateFromError() do different jobs
This distinction is worth understanding.
getDerivedStateFromError() updates state so the boundary can switch to fallback UI.
componentDidCatch() is the place for side effects such as logging.
That means a sensible boundary often uses both:
- one for changing what is rendered
- one for reporting what happened
Keeping those responsibilities separate makes the component easier to reason about.
Error Boundaries Do Not catch Everything
This is the part developers usually need to learn quickly.
Error boundaries do not catch errors from:
- event handlers
- asynchronous callbacks like
setTimeout - server‑side rendering
- errors thrown inside the boundary itself
That list matters because people often expect a boundary to work like a global try/catch for the whole app. It is not that.
If an error happens in a click handler, for example, ordinary JavaScript error handling is still needed. The boundary only helps with render‑phase and lifecycle‑related failures in the component tree beneath it.
Placement Strategy Matters
Wrapping the entire application in one giant error boundary is possible, but it is rarely the most helpful arrangement on its own.
If the entire app is inside a single boundary, one component failure may replace the whole interface with one fallback screen.
That can still be useful as a last‑resort safety net. But many applications also benefit from smaller boundaries around isolated sections:
- route content
- sidebars
- dashboard panels
- widgets
- third‑party integrations
This is where the feature becomes architectural rather than just defensive.
Boundaries are Especially Useful Around Less Trusted Components
Some parts of the tree are more failure‑prone than others:
- newly migrated code
- complicated data rendering
- third‑party wrappers
- unstable feature areas
Those are natural candidates for local boundaries because they let the rest of the page survive if that section fails.
They are Not a Substitute for Fixing Bugs
This should be obvious, but it is still worth stating.
An error boundary is not permission to leave fragile code in place. It is there to protect the user experience while we fix issues properly and gather useful logs.
If a boundary keeps firing in production, that is a signal that the underlying problem still needs attention.
The Component is Class‑Based for a Reason
At the time of writing, error boundaries are implemented with class component APIs.
That can look slightly awkward in an application increasingly built with function components, but it is not a contradiction. The boundary can still wrap function components perfectly well. The boundary itself just happens to be written as a class.
This is a good reminder that React features do not all arrive in one stylistic era at once.
Logging is Part of the Value
If an error boundary only renders fallback UI and discards the actual error details, half the opportunity is lost.
componentDidCatch() is the obvious place to connect to logging, diagnostics, or reporting tools. That turns the boundary from a silent bandage into an observability point.
Containing failure for the user is useful. Learning why it happened is just as useful for the team.
Think of Error Boundaries as Fault Lines
That is the most useful mental model.
They mark the places where one part of the UI is allowed to fail without dragging unrelated parts down with it.
When those lines are placed well, the application feels sturdier. When they are placed badly, either too much survives in a broken state or too much gets taken down unnecessarily.
They Improve Resilience by Making Failure Local
That is the real lesson.
React error boundaries are not glamorous, but they are one of the clearer examples of the framework encouraging better operational thinking. Failures happen. The question is whether one failure should be allowed to wipe out everything around it.
Usually, the answer is no.
Used thoughtfully, error boundaries let us turn that answer into actual interface behaviour.
Related Articles

Manipulate Elements with CSS transform. Manipulate Elements with CSS

Building a Headless CMS‑Powered Site with Next.js. Building a Headless CMS‑Powered Site with Next.js

The arguments Object vs. Rest Parameters in JavaScript. The
argumentsObject vs. Rest Parameters in JavaScript
Sorting Objects in JavaScript. Sorting Objects in JavaScript

3Sum Closest in JavaScript: Sorting and Two Pointers. 3Sum Closest in JavaScript: Sorting and Two Pointers

Find Peak Element: Binary Search Without a Fully Sorted Array. Find Peak Element: Binary Search Without a Fully Sorted Array

Understanding the Nullish Coalescing (??) Operator in JavaScript. Understanding the Nullish Coalescing (
??) Operator in JavaScript
Longest Substring Without Repeating Characters in JavaScript. Longest Substring Without Repeating Characters in JavaScript

Use JavaScript to Find the Week Day from a Date. Use JavaScript to Find the Week Day from a Date

Rethinking Carousels: Going Around in Circles. Rethinking Carousels: Going Around in Circles

Memoization in JavaScript: Optimising Function Calls. Memoization in JavaScript: Optimising Function Calls

Object.keys(), Object.values(), and Object.entries() Explained. Object.keys(),Object.values(), andObject.entries()Explained