Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested ErrorBoundary

Tags:

reactjs

I am thinking of performing nested error boundaries in ReactJS for a specific use case:

  • to show an error view in the child components
  • to show an error dialog in the parent component
    <ErrorBoundary1>
        <ErrorBoundary2><child1 /></ErrorBoundary2>
        <ErrorBoundary2><child2 /></ErrorBoundary2>
    </ErrorBoundary1>

I already tried to do it, but it seems like the parent error boundary is not being passed through when an error happened. I can perform a throw in the componentDidCatch of the inner error boundary but this will put it into an infinite loop.

Suggestions?

like image 431
Kerwin Jorbina Avatar asked Jul 17 '18 17:07

Kerwin Jorbina


Video Answer


1 Answers

Nested error boundaries are a thing, but the parent will only come into play if the child boundary fails (an error in render or, as you discovered, componentDidCatch). Though I can't replicate your experience of the inner boundary looping: it dies immediately on throwing.

class DialogErrorBoundary extends React.Component {
  state = {
    hasError: false
  };

  static getDerivedStateFromError() {
    return {
      hasError: true
    };
  }

  render() {
    return this.state.hasError ? <div>DIALOG ERROR</div> : this.props.children;
  }
}

class ErrorBoundary extends React.Component {
  state = {
    hasError: false
  };

  componentDidCatch(error) {
    throw error;
  }

  static getDerivedStateFromError(error) {
    return {
      hasError: true
    };
  }

  render() {
    return this.state.hasError ? <div>ERROR</div> : this.props.children;
  }
}

class SomeComponent extends React.Component {
  componentDidMount() {
    throw Error("Nope.");
  }

  render() {
    return <div>SOME COMPONENT</div>;
  }
}

function App() {
  return (
    <DialogErrorBoundary>
      <ErrorBoundary>
        <SomeComponent />
      </ErrorBoundary>{" "}
    </DialogErrorBoundary>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

To implement your suggestion, this leaves us with the usual means of communication between components:

  • a function passed from the parent component
  • shared state, Redux et al

The rough goal would be: if there's a parent boundary, notify it that the child boundary has caught an error.

However at this point we're not leveraging the error boundary mechanism, simply notifying a component to display a dialog. So, while there is an argument for having a "catch-all" error boundary at the root of an application, it cannot realistically come into play until its child boundaries have failed.

like image 137
Rich Churcher Avatar answered Nov 15 '22 08:11

Rich Churcher