React: React to not unmount the entire tree on uncaught errors

Created on 14 Jun 2018  路  3Comments  路  Source: facebook/react

Do you want to request a feature or report a bug?
Feature request

What is the current behavior?
Whole app unmounts on uncaught errors.

What is the expected behavior?
It'd be good to just unmount the affected tree.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
React@16

Hi guys, I feel like the "new" error handling approach on React 16 is too harsh for our App. We have plenty of plugin "entrypoints" for external React components that we consider error prone. While having an ErrorBoundary for each is a solution, I'd prefer that only the affected component tree to be unmounted in case some of these components, or even internal components spits an error.

A way to achieve this with the new error handling system would be to:

  1. This behavior could be a opt-in or out defined on a component up in the tree, something like a class variable supressErrors = true.
  2. Flag the component that threw the error.
  3. Re-render the whole tree.
  4. Do not render flagged components.

The effect would be like a default ErrorBoundary wrapping every component down the tree where the boundary just spits null instead of crashing the whole app.

What do you think?

Most helpful comment

It is sometimes suggested that a better solution would be to leave null in place of failing components. I think it might sound better intuitively but it's pretty bad in practice.

Things randomly popping off the screen on errors leads to a pretty jarring user experience. Imagine that if in JS, whenever a function threw an error, it would be treated as if it returned null instead. That might work sometimes, cause further errors in other cases, and lead to some very wrong behavior in yet other cases.

For example, imagine a shopping cart UI where some items in the checkout form just disappear. Now you might accidentally buy more things than you need. Or imagine a status update form with a privacy selector disappearing. Now you might accidentally post something with a public visibility while thinking you're only sharing with friends.

So overall, this is a pretty dangerous idea and we won't do this by default. If you feel very strongly that this is a good solution, you can always explicitly wrap every component in an error boundary (e.g. via a HOC). But we recommend against this, and instead suggest to design errors as intentional states at an appropriately coarse granularity level.

All 3 comments

It is sometimes suggested that a better solution would be to leave null in place of failing components. I think it might sound better intuitively but it's pretty bad in practice.

Things randomly popping off the screen on errors leads to a pretty jarring user experience. Imagine that if in JS, whenever a function threw an error, it would be treated as if it returned null instead. That might work sometimes, cause further errors in other cases, and lead to some very wrong behavior in yet other cases.

For example, imagine a shopping cart UI where some items in the checkout form just disappear. Now you might accidentally buy more things than you need. Or imagine a status update form with a privacy selector disappearing. Now you might accidentally post something with a public visibility while thinking you're only sharing with friends.

So overall, this is a pretty dangerous idea and we won't do this by default. If you feel very strongly that this is a good solution, you can always explicitly wrap every component in an error boundary (e.g. via a HOC). But we recommend against this, and instead suggest to design errors as intentional states at an appropriately coarse granularity level.

Cool @gaearon - thanks for the links. Feels bad for bringing the topic up again - I totally get the point and am 100% on the ErrorBoundary wagon, it really improved how we handle errors in React.
I've read the others discussions and they don't seem as generic.

While I see the benefit it brings, I think that there could be a opt-in that we could supress errors intentionally on a sub-tree, it could be something like DANGER_YOUR_APP_WILL_CHEAT_YOU to make sure developers understand it is dangerous.

Another alternative could be a component. Instead of returning null we could return a component that will show the error on the place it happened in this case, the UI would not hide the errors and also we'd have a fallback for every component without an ErrorBoundary.

// not sure how retry would work, clear flags and re-render?
const DefaultError = <div>Something went wrong rendering this component<button>Retry</button></div>

class MyExternalWidgerRenderer extends   PureComponent {
  ...
  // needs help naming things
  DefaultErrorBoundary: (error, info) => Node = DefaultError
  or
  SupressErrorComponent: (error, info) => Node = DefaultError

....

I can see the point that implementing something like this would encourage writing less error boundaries, but it doesn't sound crazy to me.

Anyways, I get the point and how React should encourage good practices - we're writing the boundaries :grin:

Was this page helpful?
0 / 5 - 0 ratings