Error Boundaries are special React components that act like safety systems on a space station. When one module fails, the Error Boundary isolates the problem and prevents the entire station from being destroyed.
An Error Boundary is a class component in React that catches JavaScript errors anywhere in its child component tree, logs them, and displays a fallback UI instead of the tree that crashed.
An Error Boundary is a class component that implements one or both of these methods:
static getDerivedStateFromError(error) - Updates state so the next render shows a fallback UIcomponentDidCatch(error, errorInfo) - Logs error information (e.g., to a monitoring service)1import React from 'react';
2
3class ErrorBoundary extends React.Component {
4 constructor(props) {
5 super(props);
6 this.state = { hasError: false, error: null };
7 }
8
9 // Called when a child component throws an error
10 // Returns an object that updates the state
11 static getDerivedStateFromError(error) {
12 return { hasError: true, error: error };
13 }
14
15 // Called after catching an error
16 // Great place for logging errors
17 componentDidCatch(error, errorInfo) {
18 console.error('Error caught:', error);
19 console.error('Component stack:', errorInfo.componentStack);
20 }
21
22 render() {
23 if (this.state.hasError) {
24 return (
25 <div className="error-fallback">
26 <h2>Something went wrong!</h2>
27 <p>{this.state.error?.message}</p>
28 </div>
29 );
30 }
31
32 return this.props.children;
33 }
34}An Error Boundary wraps the components you want to protect:
1function SpaceStation() {
2 return (
3 <div className="station">
4 <ErrorBoundary>
5 <Navigation />
6 </ErrorBoundary>
7
8 <ErrorBoundary>
9 <MainPanel />
10 </ErrorBoundary>
11
12 <ErrorBoundary>
13 <StatusBar />
14 </ErrorBoundary>
15 </div>
16 );
17}Now if
MainPanel throws an error, Navigation and StatusBar will still work!You can use different levels of granularity:
1function App() {
2 return (
3 <ErrorBoundary fallback={<h1>Entire station failure!</h1>}>
4 <SpaceStation />
5 </ErrorBoundary>
6 );
7}1function SpaceStation() {
2 return (
3 <div>
4 <ErrorBoundary fallback={<p>Navigation offline</p>}>
5 <Navigation />
6 </ErrorBoundary>
7 <ErrorBoundary fallback={<p>Control panel unavailable</p>}>
8 <ControlPanel />
9 </ErrorBoundary>
10 </div>
11 );
12}1function Dashboard() {
2 return (
3 <div className="dashboard">
4 {widgets.map(widget => (
5 <ErrorBoundary key={widget.id} fallback={<WidgetError />}>
6 <Widget data={widget} />
7 </ErrorBoundary>
8 ))}
9 </div>
10 );
11}It's important to know that Error Boundaries do not catch errors in:
try/catchsetTimeout, fetch, Promise1// Event handler - requires try/catch
2function Button() {
3 const handleClick = () => {
4 try {
5 riskyOperation();
6 } catch (err) {
7 // Handle the error here
8 }
9 };
10 return <button onClick={handleClick}>Click</button>;
11}The best practice is to create a reusable Error Boundary with a configurable fallback:
1class ErrorBoundary extends React.Component {
2 constructor(props) {
3 super(props);
4 this.state = { hasError: false, error: null };
5 }
6
7 static getDerivedStateFromError(error) {
8 return { hasError: true, error };
9 }
10
11 componentDidCatch(error, info) {
12 console.error('Error boundary caught:', error, info);
13 }
14
15 render() {
16 if (this.state.hasError) {
17 // Use the fallback prop if available
18 if (this.props.fallback) {
19 return this.props.fallback;
20 }
21 return <h2>An error occurred</h2>;
22 }
23 return this.props.children;
24 }
25}
26
27// Usage with custom fallback
28<ErrorBoundary fallback={<p>Module damaged, but the station is running!</p>}>
29 <RiskyModule />
30</ErrorBoundary>