<p dir="auto"><strong>Do you want to request a <em>feature</em> or report a <em>bug</em>?</strong></p>
<p dir="auto">Not sure tbh.</p>
<p dir="auto"><strong>What is the current behavior?</strong></p>
<p dir="auto">I have global handler for unhandled errors:<br>
window.addEventListener('error', (evt) =&gt; ...)</p>
<p dir="auto">Now when I use the componentDidCatch function it gets called correctly when render throws an exception but that global error event is also triggered - and before the componentDidCatch call.</p>
<p dir="auto"><strong>What is the expected behavior?</strong></p>
<p dir="auto">Since componentDidCatch handles the error I'd prefer if the global event wasn't triggered, same as with a usual try-catch block.</p>
<p dir="auto">Or is there at least some way to  figure out from the evt object in the event handler that the exception is caught by react?</p>
<p dir="auto">I hope this made sense...</p>
<p dir="auto">I'm trying to make use of componentDidCatch in the React 16 beta. I already had a global window error handler which was working fine, but it unexpectedly catches errors that I would expect componentDidCatch to have handled. That is, component-local errors are being treated as window-global errors in dev builds.</p>
<p dir="auto">The problem seems to stem from <code class="notranslate">invokeGuardedCallbackDev</code> in <code class="notranslate">ReactErrorUtils.js</code>. I think that this entire <code class="notranslate">__DEV__</code> block of code is problematic. The stated rational is:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="  // In DEV mode, we swap out invokeGuardedCallback for a special version
  // that plays more nicely with the browser's DevTools. The idea is to preserve
  // &quot;Pause on exceptions&quot; behavior. Because React wraps all user-provided
  // functions in invokeGuardedCallback, and the production version of
  // invokeGuardedCallback uses a try-catch, all user exceptions are treated
  // like caught exceptions, and the DevTools won't pause unless the developer
  // takes the extra step of enabling pause on caught exceptions. This is
  // untintuitive, though, because even though React has caught the error, from
  // the developer's perspective, the error is uncaught."><pre class="notranslate"><code class="notranslate">  // In DEV mode, we swap out invokeGuardedCallback for a special version
  // that plays more nicely with the browser's DevTools. The idea is to preserve
  // "Pause on exceptions" behavior. Because React wraps all user-provided
  // functions in invokeGuardedCallback, and the production version of
  // invokeGuardedCallback uses a try-catch, all user exceptions are treated
  // like caught exceptions, and the DevTools won't pause unless the developer
  // takes the extra step of enabling pause on caught exceptions. This is
  // untintuitive, though, because even though React has caught the error, from
  // the developer's perspective, the error is uncaught.
</code></pre></div>
<p dir="auto">This is misguided because it's not about pausing on exceptions, it's about "pause on <em>uncaught</em> exceptions." However, <code class="notranslate">componentDidCatch</code> makes exceptions <em>caught</em>!</p>
<p dir="auto">Rather than switching on prod vs dev and using try/catch in prod and window's error handler in dev, React should always use try/catch, but rethrow if you reach the root without hitting a componentDidCatch handler. This would preserve the correct "pause on uncaught exceptions" behavior without messing with global error handlers.</p>