Performance: Error boundaries concept
Error boundaries affect the user experience by preventing the entire React app from crashing when a component error occurs, improving interaction responsiveness.
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { return { hasError: true }; } render() { if (this.state.hasError) { return <div>Something went wrong.</div>; } return this.props.children; } } function BuggyComponent() { throw new Error('Crash!'); } function App() { return ( <ErrorBoundary> <BuggyComponent /> </ErrorBoundary> ); }
function BuggyComponent() { throw new Error('Crash!'); return <div>Won't render</div>; } function App() { return <BuggyComponent />; }
| Pattern | DOM Operations | Reflows | Paint Cost | Verdict |
|---|---|---|---|---|
| No error boundary | Full tree unmount and remount on error | Multiple reflows due to full app reload | High paint cost due to blank screen and reload | [X] Bad |
| With error boundary | Only error boundary subtree replaced | Single reflow limited to fallback UI | Low paint cost with stable UI fallback | [OK] Good |
Error Boundary in React?componentDidCatch and getDerivedStateFromError lifecycle methods.componentDidCatch and getDerivedStateFromError lists these two required methods correctly.ChildComponent throws an error?
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, info) {
console.log('Error logged:', error);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
// Usage:
// <ErrorBoundary><ChildComponent /></ErrorBoundary>ChildComponent throws an error, getDerivedStateFromError sets hasError to true.hasError is true, the component renders the fallback UI: <h1>Something went wrong.</h1>.class MyErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { error: null };
}
componentDidCatch(error, info) {
this.setState({ error });
}
render() {
if (this.state.error) {
return <h2>Error occurred</h2>;
}
return this.props.children;
}
}getDerivedStateFromError to update state when an error happens.componentDidCatch to set state, which is incorrect because componentDidCatch is for side effects, not state updates.class LoggingErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, info) {
// ???
}
render() {
if (this.state.hasError) {
return <div><h1>Oops!</h1><p>Try refreshing.</p></div>;
}
return this.props.children;
}
}
What should replace // ??? to correctly log errors without causing issues?Pass the test and this pattern moves unknown