React 服务器端渲染内存泄漏



下面的代码根据链接反应说:

不幸的是,这可能会导致服务器渲染的内存泄漏(其中 组件将卸载永远不会被调用)

// Before
class ExampleComponent extends React.Component {
componentWillMount() {
this.setState({
subscribedValue: this.props.dataSource.value,
});
// This is not safe; it can leak!
this.props.dataSource.subscribe(
this.handleSubscriptionChange
);
}
componentWillUnmount() {
this.props.dataSource.unsubscribe(
this.handleSubscriptionChange
);
}
handleSubscriptionChange = dataSource => {
this.setState({
subscribedValue: dataSource.value,
});
};
}

我不明白这怎么可能是服务器端的内存泄漏。例如,假设我们有这段代码,它在服务器端呈现,并且 ExampleComponent 包含内存泄漏。

import React from 'react';
import ReactDomServer from 'react-dom/server';
import App from './components/index'
const serverRender =  () =>{
return ReactDomServer.renderToString(<ExampleComponent />);
};
export default serverRender;

当它返回到客户端时,呈现的组件不会附加到任何位置,并且已准备好进行 GB 收集。那么为什么会出现内存泄漏呢?

答案在文档中有所暗示:

人们通常认为componentWillMountcomponentWillUnmount总是配对的,但这并不能保证

显而易见的原因是componentWillMount在组件即将挂载时运行,因此如果挂载中断,则组件将永远不会挂载,因此永远不会卸载。但是,在文档中的上一节中也有提示的原因,其中显示了代码:

componentWillMount() {
this.setState({
subscribedValue: this.props.dataSource.value,
});
// This is not safe; it can leak!
this.props.dataSource.subscribe(
this.handleSubscriptionChange
);
} 

并说

上面的代码对于服务器呈现(不使用外部数据)和即将推出的异步呈现模式(请求可能会多次启动)都是有问题的。

由此可以假设componentWillMount确实在 SSR 期间运行,并且在客户端冻结时也运行,这意味着正在发出额外的不必要的请求,从而导致服务器上的潜在内存泄漏。

但是,如果您使用componentDidMount则可以保证:

  1. 仅在客户端运行
  2. 确保componentWillUnmount之后始终运行

this.props.dataSource是外部的东西,可以比调用subscribe的组件活得更长。handleSubscriptionChange将由this.props.dataSource引用。此外,组件本身也可能被handleSubscriptionChange内部的this引用。所以 GB 根本不会清理ExampleComponent

由于组件将挂载已被弃用,您可能不必担心这些细节,而只需使用componentDidMaount

最新更新