Performance: Why error boundaries matter
Error boundaries affect user experience by preventing full app crashes and reducing layout shifts caused by unhandled errors.
Jump into concepts and practice - no test required
import { ErrorBoundary } from 'react-error-boundary'; function ErrorFallback() { return <div role="alert">Something went wrong.</div>; } function MyComponent() { const data = JSON.parse('invalid json'); return <div>{data.name}</div>; } export default function App() { return ( <ErrorBoundary FallbackComponent={ErrorFallback}> <MyComponent /> </ErrorBoundary> ); }
function MyComponent() { // No error boundary const data = JSON.parse('invalid json'); // throws error return <div>{data.name}</div>; }
| Pattern | DOM Operations | Reflows | Paint Cost | Verdict |
|---|---|---|---|---|
| No error boundary, error crashes app | Full tree unmount and remount | Multiple reflows due to layout shifts | High paint cost from blank screen and re-render | [X] Bad |
| Error boundary with fallback UI | Only fallback UI rendered | Single reflow, minimal layout shift | Low paint cost, stable UI | [OK] Good |
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error, info) {
this.setState({ hasError: true });
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
function BuggyComponent() {
throw new Error('Bug!');
return <div>No bugs</div>;
}
// Usage
<ErrorBoundary>
<BuggyComponent />
</ErrorBoundary>function ErrorBoundary({ children }) {
try {
return children;
} catch (error) {
return <div>Error occurred</div>;
}
}