React Interview Questions

39 Questions
React.js

React.js

FrontendWeb Development

Question 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 or requestAnimationFrame callbacks).
    • Server-side rendering.
    • Errors thrown in the error boundary itself (rather than its children).

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

  1. Use Error Boundaries Strategically: Wrap the top-level components or key parts of the application where errors are most likely to occur.
  2. Provide User-Friendly Fallback UIs: Display meaningful messages or alternative UIs to keep the user informed.
  3. Log Errors for Analysis: Use services like Sentry, LogRocket, or your own logging system to track errors in production.
  4. 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.

Recent job openings