Javascript 在什么情况下可以卸载根组件?

Javascript 在什么情况下可以卸载根组件?,javascript,reactjs,Javascript,Reactjs,我有一个根组件,它初始化并托管整个应用程序,简化后看起来像 class App extends React.Component { componentDidMount() { // initialisation here } componentWillUnmount() { // I expect this to never happen } render() { // the whole app is

我有一个根组件,它初始化并托管整个应用程序,简化后看起来像

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

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

    render() {
        // the whole app is rendered here
    }
}
它在页面上的呈现非常简单(我只做了一次,该脚本在页面加载时运行,不会再次调用)

ReactDOM.render(,domeElement);
我最近发现,
应用程序
组件将卸载
有时(极少)会被调用

上次它发生在移动Chrome67上,但在桌面上也观察到了

我用一个虚拟的
raven.captureMessage('application will unmount')捕获了那个事件
(其中,
raven
是一个sentry客户端),所以目前我还没有更多的细节

但我完全感到惊讶:在什么情况下,react可以卸载根组件?没有JS触及react托管DOM,最后一次发生在我认识的一个人的手机上,它是一个普通的chrome浏览器,没有任何修改

我和那个人谈过——他们提到应用程序在视觉上看起来很正常(但由于明显的原因,它不能正常工作——因为我在那里取消了初始化)

另一个奇怪的时刻是,我还记录了该组件的
componentDidMount
是否多次发生(通过模块范围的变量),并且它没有被调用

总结一下:调用了
componentWillUnmount
,没有删除DOM节点,没有调用连续的
componentDidMount
(这个序列听起来让我难以置信,但这就是我观察到的)

另一件重要的事情:对于最近的案例,它发生在chrome解除选项卡休眠之后(chrome在选项卡休眠或其他选项卡需要ram/cpu时将其置于休眠状态)


我在这里遗漏了什么吗?

一种情况是使用
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);
constrootelement=document.getElementById('root');
const OtherComponent=()=>测试

; 类应用程序扩展组件{ 组件将卸载(){ log('will unmount'); } handleRenderOtherComponent=()=>{ render(,rootElement); }; render(){ 返回( 除根 ); } }
ReactDOM.render(

并且您没有直接或通过某种包装库间接地调用
ReactDOM.unmountComponentAtNode
任何地方?@djfdev
grep
for
unmountComponentAtNode
显示它仅在react本身和reactstrap库中显示。在后一种情况下,它应用于modal
div
。我确定不要直接调用它,
ReactDOM.render(,domeElement);
实际上是我唯一可以引用
App
的地方。@zerkms如果你找到了原因,我真的很想知道。我发现如果你在保存代码时创建一个codesandbox,
componentWillUnmount()根组件的
正在被调用。但这可能是因为他们如何处理沙盒和模拟浏览器窗口的几个原因。@trixn因为它不可能重现-调试将花费相当长的时间:-D我将一次添加一件事到
哨兵
日志消息以获得更深入的信息。是的,我将保持此帖子的更新ating@zerkms也许您可以抛出一个捕获到的错误来记录堆栈跟踪。这可能有助于理解错误调用方是谁。在我的情况下,我对这个想法投了赞成票,尽管我只渲染了一次(很抱歉在问题中没有提到它,现在已修复)这在react应用程序中呈现新的根组件是常见的吗?我还想知道何时调用根组件中的componentWillUnmountnormally@techguy2000大多数情况下,react应用程序是一个单页应用程序,只有一个根组件从未卸载。当父级不再呈现组件时,该组件将卸载。根组件没有可以卸载它的父组件。但是,由于呈现过程中出现未处理的错误,它可能会被卸载。没有任何限制可以阻止您在同一页上呈现多个根组件。这些都是相互相邻运行的独立应用程序。可能是其他wi上的一些小部件,如小组件se静态页面。
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);