Repository: material-ui
Issue: [ErrorBoundary] New ErrorBoundary Component
Labels: new feature

<!-- Provide a general summary of the feature in the Title above -->
This ticket is to track ideas/rationale for material-ui including an ErrorBoundary component.

I would like to contribute this component to material-ui, as described below.

- [x] I have searched the [issues](https://github.com/mui-org/material-ui/issues) of this repository and believe that this is not a duplicate.

## Summary 💡

[ErrorBoundaries](https://reactjs.org/docs/error-boundaries.html) are a React 16+ specific feature that uses the [componentDidCatch](https://reactjs.org/docs/react-component.html#componentdidcatch) API for handling uncaught errors without unmounting the whole React component tree.

This ticket exists to request feedback and ideas for a material-ui-provided ErrorBoundary component.

<!-- Describe how it should work. -->

## Examples 🌈

[The react-ui-roundup tracks ErrorBoundaries](https://github.com/dimitropoulos/react-ui-roundup#errorboundary), and it appears that there are just 3 implementations:

<a href="https://github.com/dimitropoulos/react-ui-roundup#errorboundary">
<img src="https://user-images.githubusercontent.com/15232461/75711292-27bf8700-5c94-11ea-9731-6ac285de25df.png" height="300px;" border="5"/>
</a>

For convenience, I've linked to the actual code for these three here:

- [Elastic's code](https://github.com/elastic/eui/blob/master/src/components/error_boundary/error_boundary.tsx):  This one is the simplest (and, best looking, in my opinion).  No props, just catches the error as you might expect. 
- [AntD's code](https://github.com/ant-design/ant-design/blob/master/components/alert/ErrorBoundary.tsx#L36): This is implemented by adapting the Alert component (I _do not_ think we should do this in this project, btw).  It therefore accepts a `title` and `description` prop (both strings), but not for passing in a custom fallback component, which is a bummer.
- [Carbon Design's code](https://github.com/carbon-design-system/carbon/blob/master/packages/react/src/components/ErrorBoundary/ErrorBoundary.js#L48): This one, although the storybook example they have is a bit unfortunate (it doesn't even show an error or callstack..???), it's actually the most flexible of the bunch.  It allows passing in a fallback component via a fallback prop.  The only downside here is that the actual error and componentStack are not accessible because they are not passed in to the fallback component.

So basically, I'm suggesting a mashup of the above 3, the looks of Eui, the simple string api of AntD, the flexible fallback (if you really need or want it), and _two more_ little additions (they're related).

I have done a few of these ErrorBoundary components for various projects in the past and one thing I ALWAYS end up needing is a little section at the bottom of the callstack where I can tell the user something like:
> Oops! Something went wrong.  Please contact support at 1-800-867-5309

Or (better) sometimes it's appropriate to have a button that the user can click to contact support that will then open up something like Intercom, will start an email with some useful information pre-populated, or will send an error report dialog with something like getSentry.

Speaking of which, mature codebases will often be tracking errors of this sort with something like getSentry, and the `onCatch` prop exists as a simple callback that will allow the user to trigger some analytics (or other change) if an error state is to occur.

I propose the following API:

```ts
import { ReactNode, ErrorInfo } from 'react';

interface ErrorBoundaryProps {
  /**
   * This inserts a section below the call stack (or fallback) but within the ErrorBoundary that you can use to provide the users with more info (such as a support phone number to call) or
   */
  actions?: ReactNode;
  
  /**
   * Can be overridden by providing a `fallback` prop.
   */
  description?: string | ((componentStack: string) => string);

  /**
   * forces the ErrorBoundary to render when debug is `true`
   */
  debug?: boolean;

  /**
   * This matches the arguments of `componentDidCatch`.
   * If provided, overrides `title` and `description` props by occupying the space where the title and description are.
  */
  renderFallback?: (error: Error, errorInfo: ErrorInfo) => ReactNode;

  /**
   * This matches the arguments of `componentDidCatch`.
   * This callback is useful for enabling sending error information to analytics.
   */
  onCatch?: (error: Error, errorInfo: ErrorInfo) => void;

  /**
   * Provide a string to override, or a function that receives the name of the error
   */
  title?: string | ((errorTitle: string) => string);
}

const ErrorBoundary: FC<ErrorBoundary> = props => { ... }
```

As far as styling goes, I think Elastic's looks best.  Perhaps we can just play around with material-ui internals and quickly find something suitable that works in both light and dark themes.

## Motivation 🔦

this was mentioned by @oliviertassinari https://github.com/mui-org/material-ui/issues/19744#issuecomment-593408040 in a comment about improving user experience.