React Interview Questions
React.js
FrontendWeb DevelopmentQuestion 32
How do you handle error boundaries in React?
Answer:
Error boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. Error boundaries help to gracefully handle runtime errors in a React application without crashing the entire app.
Key Concepts
- Error boundaries only catch errors in the lifecycle methods, render method, and constructors of the whole tree below them. They do not catch errors for:
- Event handlers (use
try/catch
blocks). - Asynchronous code (e.g.,
setTimeout
orrequestAnimationFrame
callbacks). - Server-side rendering.
- Errors thrown in the error boundary itself (rather than its children).
- Event handlers (use
Creating an Error Boundary
To create an error boundary, you define a class component that implements either or both of the lifecycle methods static getDerivedStateFromError
and componentDidCatch
.
Example:
import React, { Component } from 'react';
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render shows the fallback UI.
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// You can also log the error to an error reporting service
console.log("Logging error: ", error, errorInfo);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
export default ErrorBoundary;
Using an Error Boundary
You can use the ErrorBoundary
component to wrap other components that you want to protect from errors.
Example:
import React from 'react';
import ErrorBoundary from './ErrorBoundary';
import MyComponent from './MyComponent';
function App() {
return (
<div>
<ErrorBoundary>
<MyComponent />
</ErrorBoundary>
</div>
);
}
export default App;
In this example, if MyComponent
throws an error during rendering, in a lifecycle method, or in its constructor, the ErrorBoundary
will catch the error and display the fallback UI ("Something went wrong.").
Example with Logging Errors
You can extend the error boundary to log errors to an external service.
Example:
import React, { Component } from 'react';
import * as Sentry from '@sentry/react'; // Example logging service
class ErrorBoundary extends Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
Sentry.captureException(error, { extra: errorInfo });
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
export default ErrorBoundary;
Handling Errors in Event Handlers
Errors in event handlers are not caught by error boundaries. You need to handle them manually.
Example:
function MyComponent() {
const handleClick = () => {
try {
// Some code that might throw an error
} catch (error) {
console.error('Caught an error:', error);
}
};
return <button onClick={handleClick}>Click me</button>;
}
Best Practices
- Use Error Boundaries Strategically: Wrap the top-level components or key parts of the application where errors are most likely to occur.
- Provide User-Friendly Fallback UIs: Display meaningful messages or alternative UIs to keep the user informed.
- Log Errors for Analysis: Use services like Sentry, LogRocket, or your own logging system to track errors in production.
- Avoid Error Boundaries in Every Component: Overusing error boundaries can mask underlying issues. Use them judiciously to maintain application stability while allowing for effective debugging.
Conclusion
Error boundaries in React provide a robust way to handle runtime errors in the component tree, ensuring that an application can gracefully recover from unexpected issues. By using error boundaries effectively, you can improve the resilience and user experience of your React applications.