React
Error Boundaries
Build safety nets that catch JavaScript errors before they crash your DataFlow dashboard.
Your DataFlow dashboard is humming along perfectly. Users are viewing charts, filtering data, clicking buttons. Then someone's internet drops during an API call. Or a prop comes back undefined from your backend. Suddenly the entire screen goes white with a cryptic error message. React components can throw errors just like regular JavaScript functions. But unlike a broken function that only affects one calculation, a broken React component can crash your entire app. Every component above it in the tree stops rendering. Your users see nothing. Error boundaries are React's answer to this problem. Think of them as try-catch blocks for your component tree. They catch JavaScript errors anywhere in their child components and display a fallback UI instead of the white screen of death.What Are Error Boundaries
An error boundary is a React component that catches JavaScript errors during rendering, in lifecycle methods, and in constructors of the whole tree below them. They're like safety nets for your UI. Error boundaries work by implementing special lifecycle methods that React calls when an error occurs. But here's the catch - error boundaries must be class components. React hooks don't have equivalents for these error-catching methods yet. Error boundaries catch errors in three places: during rendering when React builds the virtual DOM, in lifecycle methods likeuseEffect, and in constructors when components initialize. They don't catch errors in event handlers, asynchronous code like setTimeout, or errors thrown in the error boundary itself.
Class Components Required
Error boundaries must be class components because React hooks don't provide error-catching capabilities. Even in modern React codebases using functional components everywhere, you'll need at least one class component for error handling.
Creating an Error Boundary
Creating an error boundary requires implementing two lifecycle methods in a class component. Thestatic getDerivedStateFromError method catches the error and updates state, while componentDidCatch handles logging and side effects.
// DataFlow error boundary to protect dashboard sections
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error) {
// Update state to show fallback UI
return { hasError: true, error: error };
}
componentDidCatch(error, errorInfo) {
// Log error for debugging
console.error('DataFlow Error:', error, errorInfo);
}
render() {
if (this.state.hasError) {
return (
<div style={{padding: '20px', textAlign: 'center'}}>
<h2>Something went wrong</h2>
<p>The DataFlow dashboard encountered an error.</p>
</div>
);
}
return this.props.children;
}
}What just happened?
The error boundary wrapped its children but didn't activate because no errors occurred. The getDerivedStateFromError method only runs when JavaScript errors are thrown during rendering.
getDerivedStateFromError method receives the error as a parameter and returns an object to update the component's state. This method runs during the render phase, so it can't perform side effects like logging. That's where componentDidCatch comes in.
The componentDidCatch method receives both the error and an error info object containing details about which component threw the error. This method runs during the commit phase, making it perfect for logging errors to external services or analytics platforms.
Triggering Error Boundaries
Error boundaries only activate when JavaScript errors occur during rendering. Event handler errors don't trigger error boundaries because they happen outside the React rendering cycle. You need to handle those separately with regular try-catch blocks.// Component that throws an error during rendering
function ProblematicChart({ data }) {
// This will crash if data is null or undefined
const revenue = data.revenue.toFixed(2);
return (
<div>
<h3>Revenue: ${revenue}</h3>
</div>
);
}
// Using it with error boundary protection
function Dashboard() {
return (
<ErrorBoundary>
<ProblematicChart data={null} />
</ErrorBoundary>
);
}What just happened?
The ProblematicChart tried to call toFixed on null, which threw a TypeError during rendering. The error boundary caught this error and displayed the fallback UI instead of crashing the entire app.
Strategic Error Boundary Placement
Where you place error boundaries determines how much of your app stays functional when errors occur. Place them too high and small errors take down large sections. Place them too low and you end up with boundary components everywhere. The DataFlow team uses a layered approach. They have a top-level error boundary that catches catastrophic errors and displays a "something went wrong" message. Then they place more specific boundaries around risky components like charts, data tables, and API-dependent sections.// Strategic error boundary placement in DataFlow
function Dashboard() {
return (
<ErrorBoundary> {/* Top-level protection */}
<Header />
<div className="dashboard-content">
<Sidebar />
<main>
<ChartErrorBoundary> {/* Chart-specific boundary */}
<RevenueChart />
<GrowthChart />
</ChartErrorBoundary>
<TableErrorBoundary> {/* Table-specific boundary */}
<TransactionTable />
</TableErrorBoundary>
</main>
</div>
</ErrorBoundary>
);
}What just happened?
The chart section threw an error, but only the chart error boundary activated. The table section and header remained fully functional. This demonstrates how proper error boundary placement isolates failures to specific features rather than crashing the entire dashboard.
Error Boundary Limitations
Error boundaries have important limitations. They don't catch errors in event handlers, asynchronous code like promises or setTimeout, server-side rendering, or errors thrown in the error boundary itself. Event handler errors need regular try-catch blocks because they execute outside React's rendering cycle. The same applies to async operations - wrap API calls in try-catch blocks or use error states in your components.Error Boundaries Won't Catch These
Event handler errors, Promise rejections, setTimeout/setInterval errors, server-side rendering errors, and errors in the error boundary component itself all bypass error boundaries. Handle these scenarios with traditional try-catch blocks and error states.
// Error boundary won't catch this event handler error
function DataControls() {
const handleExport = () => {
try {
// This error won't trigger error boundaries
const data = null;
data.forEach(item => console.log(item));
} catch (error) {
console.error('Export failed:', error);
// Show user-friendly error message
}
};
return (
<button onClick={handleExport}>
Export Data
</button>
);
}Production Error Handling
In production, error boundaries become crucial for user experience and debugging. You want to show users helpful error messages while logging detailed error information for your development team. The DataFlow team integrates their error boundaries with services like Sentry or LogRocket for comprehensive error tracking. Error boundaries in production should provide recovery options when possible. Reset buttons, refresh suggestions, or fallback content help users continue their work even when errors occur. Notion's interface handles component failures gracefully by showing inline error states that don't disrupt the entire page.Development Mode
Show detailed error messages, stack traces, and component trees. Help developers debug issues quickly.
Production Mode
Display user-friendly messages, provide recovery actions, and log errors to monitoring services.
Quiz
1. The DataFlow team needs to create an error boundary. Which two lifecycle methods must they implement in their class component?
2. A DataFlow button click handler throws an error when processing export data. What type of error will an error boundary NOT catch?
3. The DataFlow dashboard has charts, tables, and a sidebar. What's the best strategy for error boundary placement?
React Best Practices
Master the essential patterns and conventions that separate professional React code from beginner implementations.