Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Under what circumstances can the root component be unmounted?

I have a root component that initialises and hosts the entire application and that when simplified looks like

class App extends React.Component {
    componentDidMount() {
        // initialisation here
    }

    componentWillUnmount() {
        // I expect this to never happen
    }

    render() {
        // the whole app is rendered here
    }
}

It's rendered on the page as simple as just (I do it just once, that script runs on page load and never is called again)

ReactDOM.render(<App />, domElement);

What I have discovered recently is that sometimes (extremely rarely) the App's componentWillUnmount is getting called.

Last time it happened on the mobile chrome 67, but also was observed on a desktop one as well.

I captured that event with a dummy raven.captureMessage('application will unmount'); (where raven is a sentry client), so at this moment I don't have any more details yet.

But it is totally surprising to me: under what circumstances can the root component be unmounted by react? No JS touches the react-managed DOM, the last occurrence happened on a phone of a person I know and it's a regular chrome browser without any modifications.

I talked to the person - and they mentioned that the application visually look normal (but for obvious reasons it did not function properly - since I deinitialise things there).

Another odd moment is that I also log if componentDidMount happened more than once (via a module-scoped variable) for that component, and it was not called.

So to summarise: the componentWillUnmount was called, the DOM node has not been removed, the consecutive componentDidMount was not called (this sequence sounds unbelievable to me, but that's what I observed).

Another important thing: for the latest case it happened exactly after the chrome un-hibernated the tab (chrome puts a tab in hibernation when it is hibernated or when other tabs need ram/cpu).

Am I missing something here?

like image 466
zerkms Avatar asked Nov 07 '22 04:11

zerkms


1 Answers

One circumstance is when you render another component into the root container with ReactDOM:

const rootElement = document.getElementById('root');
const OtherComponent = () => <p>test</p>;

class App extends Component {    
    componentWillUnmount() {
        console.log('will unmount');
    }

    handleRenderOtherComponent = () => {
        ReactDOM.render(<OtherComponent />, rootElement);
    };

    render() {
        return (
            <button onClick={this.handleRenderOtherComponent}>
                remove root
            </button>
        );
    }
}

ReactDOM.render(<App />, rootElement);

Edit 1vp8o058p3

like image 83
trixn Avatar answered Nov 15 '22 07:11

trixn