Skip to content

App unmounts on caught error #12865

@JakobJingleheimer

Description

@JakobJingleheimer

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

What is the current behavior?
Basically 3 levels of components

App
    Shell
        Header
        view // "children" via react-router
        Footer
Shell.tsx (catches)
class Shell extends React.Component {
    state: ShellState = {
        alerts: [],
    }

    componentDidCatch(err, info) {
        const alert = new Alert(err);
        this.setState({ alerts: _.concat(alerts, alert) });
        debugger; // all good in the neighbourhood
    }

    render() {
        return (
            <React.Fragment>
                <Header alerts={this.state.alerts} />
                {this.props.children}
                <Footer />
            </React.Fragment>
        );
    }
}
SomeView.tsx (always throws in render)
class SomeView extends React.Component {
    // …

    render() {
        throw new Error('test');
    }
}

Shell.componentDidCatch() fires and does its thing (no new errors thrown), but the app still unmounts anyway.

I understand why this is happening: SomeView's render always throws an error, so after the componentDidCatch handles the error and Shell re-renders, SomeView throws again, and apparently React shuts down (probably as an easy way to avoid an endless loop).

What is the expected behavior?

App does not unmount; abort/blacklist/ignore the miscreant component (which could be N-levels deep in the app).

I expect it to work like the codepen example.

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

No, before v16 React did not explode (to use less colourful language than this deserves).

react 16.3.1


This componentDidCatch is both neat and horrendous:

  • Neat in that there is a (mostly) standard way to catch and handle errors.
  • Horrendous in that it unmounts the entire app, creating an unrecoverable state (have you seen Spotify lately?). If anything, the unmounting should be a development-only bug-pretending-to-be-a-feature that can be disabled (because this is hella annoying and any cursory google search on it clearly shows countless hours wasted).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions