Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

componentDidCatch + window.addEventListener('error', cb) don't behave as expected

I have a componentDidCatch error boundary on my root component, to render a nice error page in case something terrible happens.

But I also have a window.addEventListener('error', cb) event handler, in case something even worse happens (outside React).

My issue now is that whenever componentDidCatch gets an error, the window error handler gets it too, so I always end up with the worst case scenario error handling, rather than the "in-react" one.

Also, it looks like the global error handler is triggered before the React error boundary, so it's not possible to mark an error as "handled" so that I can manually ignore it later.

Here's a CodePen showing my issue:
https://codepen.io/FezVrasta/pen/MNeYqN

A minimal code example would be:

class App extends React.Component {
  componentDidCatch(err) {
    console.log('react handled error', err);
  }
  render() {
    return 'foobar';
  }
}

window.addEventListener('error', err => console.log('global error', err));

// on error, I get:
// 'global error', err
// 'react handled error', err

On the contrary, with just JavaScript, the local error handler would prevent the error from reaching the window error handler.

https://codepen.io/FezVrasta/pen/eqzrxO?editors=0010

try {
  throw new Error('error');
} catch (err) {
  alert('scoped error');
}

window.addEventListener('error', () => alert('global error'))

Is this expected behavior? Can you think of a way to make it work as I'd like it to?

like image 667
Fez Vrasta Avatar asked Jul 25 '19 08:07

Fez Vrasta


Video Answer


1 Answers

Seems like this is just a development behaviour. Please take a look at this comment

In development environment, React uses a trick: caught exceptions are thrown inside a fake DOM event which makes them reported by window.onerror, but then React actually catches them so that they don't propagate up (in case there is an error boundary — otherwise they are rethrown).

In production errors caught by error boundaries stay caught.

I've just tested your example in production and alert does not show when error is thrown in render method.

like image 114
zhuber Avatar answered Oct 20 '22 13:10

zhuber