Реагировать на утечку памяти при рендеринге на стороне сервера - PullRequest
2 голосов
/ 22 марта 2019

Код ниже по ссылке реаги говорит о том, что:

К сожалению, это может привести к утечкам памяти при рендеринге сервера (где componentWillUnmount никогда не будет вызываться)

// 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;

Когда это возвращается клиенту, визуализированные компоненты никуда не присоединяются и готовыбыть ГБ собранным.Так почему же происходит утечка памяти?

Ответы [ 2 ]

1 голос
/ 22 марта 2019

Ответ намекается в документах:

Люди часто предполагают, что componentWillMount и componentWillUnmount всегда связаны, но это не гарантируется

Существует очевидная причина в том, что 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 всегда будет работать потом
0 голосов
/ 22 марта 2019

this.props.dataSource является чем-то внешним и может жить дольше, чем компонент, вызывающий subscribe. На handleSubscriptionChange будет ссылаться this.props.dataSource. Также на сам компонент может ссылаться this внутри handleSubscriptionChange. Так что ГБ вообще не очистит ExampleComponent.

Поскольку componentWillMount устарело, вам, вероятно, не стоит беспокоиться об этих деталях, а просто используйте componentDidMaount.

...