Error boundaries are React components that catch JavaScript errors in their child component tree and show a fallback UI instead of letting the whole application crash. You can think of them as a safety layer around part of your interface.
Without an error boundary, a rendering error can break a large part of the UI. With an error boundary, you can show a friendly message such as "Something went wrong" and keep the rest of the application working.
A classic error boundary is a class component that uses two special methods:
static getDerivedStateFromError(error) to update state and show fallback UIcomponentDidCatch(error, errorInfo) to log details about the errorWhen a child component throws during rendering, the boundary catches it and can render something else instead of the broken subtree.
import { Component } from 'react'
class ErrorBoundary extends Component {
constructor(props) {
super(props)
this.state = {
hasError: false,
error: null
}
}
static getDerivedStateFromError(error) {
return {
hasError: true,
error
}
}
componentDidCatch(error, errorInfo) {
console.error('Caught by ErrorBoundary:', error)
console.error('Component stack:', errorInfo.componentStack)
}
render() {
if (this.state.hasError) {
return (
<div>
<h2>Something went wrong.</h2>
<p>{this.state.error?.message}</p>
</div>
)
}
return this.props.children
}
}
export default ErrorBoundary
You wrap the components you want to protect. If one of those components throws an error during rendering, the boundary shows fallback content instead.
import ErrorBoundary from './ErrorBoundary'
function BuggyComponent() {
throw new Error('This component crashed')
}
function App() {
return (
<ErrorBoundary>
<BuggyComponent />
</ErrorBoundary>
)
}
If BuggyComponent throws an error while rendering, the rest of the app does not necessarily disappear. Instead, the boundary can show a safe fallback message.
This is one of the most important things to understand. Error boundaries are helpful, but they are not a universal replacement for try...catch.
If an error happens inside a button click or another event handler, you must handle it yourself with normal JavaScript error handling.
function SaveButton() {
const handleClick = async () => {
try {
await saveData()
} catch (error) {
console.error('Save failed:', error)
}
}
return <button onClick={handleClick}>Save</button>
}
You can place one error boundary high in the app, or place several smaller boundaries around risky sections. In real projects, smaller boundaries are often better because they isolate failures more precisely.
For example, on a dashboard you might wrap the chart, activity feed, and user list separately. If the chart crashes, the other panels can still render.
function Dashboard() {
return (
<div>
<ErrorBoundary>
<RevenueChart />
</ErrorBoundary>
<ErrorBoundary>
<UserList />
</ErrorBoundary>
<ErrorBoundary>
<ActivityFeed />
</ErrorBoundary>
</div>
)
}
A good fallback UI should be clear and useful. Instead of only showing a technical error message, you can show a user-friendly message, a reload button, or a retry option.
class ErrorBoundary extends Component {
constructor(props) {
super(props)
this.state = { hasError: false }
}
static getDerivedStateFromError() {
return { hasError: true }
}
resetBoundary = () => {
this.setState({ hasError: false })
}
render() {
if (this.state.hasError) {
return (
<div>
<h2>This section failed to load.</h2>
<p>Please try again.</p>
<button onClick={this.resetBoundary}>Try Again</button>
</div>
)
}
return this.props.children
}
}
Many React developers use the react-error-boundary package because it gives a simpler API and useful helper patterns. It still solves the same problem, but it feels easier to use in modern React applications.
import { ErrorBoundary } from 'react-error-boundary'
import ErrorFallback from './ErrorFallback'
function App() {
return (
<ErrorBoundary
FallbackComponent={ErrorFallback}
onError={(error, info) => {
console.error('Logged error:', error)
console.error(info.componentStack)
}}
>
<ProfilePage />
</ErrorBoundary>
)
}
function ErrorFallback({ error, resetErrorBoundary }) {
return (
<div role="alert">
<h2>Something went wrong</h2>
<p>{error.message}</p>
<button onClick={resetErrorBoundary}>Try Again</button>
</div>
)
}
export default ErrorFallback
Error boundaries make React apps safer by catching rendering errors in child components and replacing broken UI with fallback content. They are especially useful in larger apps where one crashing widget should not take down the rest of the interface.
They are not a replacement for all error handling, but they are an important stability tool. Combined with good logging and targeted placement, they make production React applications much more resilient.
Explore 500+ free tutorials across 20+ languages and frameworks.