#javascript #node.js #reactjs #memory-leaks #garbage-collection
#javascript #node.js #reactjs #утечки памяти #сборка мусора
Вопрос:
У меня есть фрагмент устаревшего кода, который отображает компонент react на сервере при каждом запросе, что делает очевидной утечку памяти. Я загнал проблему в угол до этого кода:
componentWillMount: function () {
var onLogin = this.props.onLogin || function () {},
onLogout = this.props.onLogout || function () {};
this.on('authChange', function () {
console.log('user authenticated:', this.state.isAuthenticated);
return this.state.isAuthenticated
? onLogin(this.state)
: onLogout(this.state);
}.bind(this));
},
Я полагаю, что при каждом запросе this
объект сохраняет нового слушателя, но я не понимаю, почему this
элемент не помечается как мусор при выполнении рендеринга компонента.
Ответ №1:
Вам необходимо отменить привязку authChange
обработчика до того, как компонент будет размонтирован. Вы можете сделать это в componentWillUnmount
.
Поскольку вы создаете функцию-обработчик, используя первые переданные реквизиты, вам следует сохранить его в свойстве, чтобы позже можно было отменить привязку:
componentWillMount: function () {
var onLogin = this.props.onLogin || function () {},
onLogout = this.props.onLogout || function () {};
this.authChange = function () {
console.log('user authenticated:', this.state.isAuthenticated);
return this.state.isAuthenticated
? onLogin(this.state)
: onLogout(this.state);
}.bind(this);
this.on('authChange', this.authChange);
},
componentWillUnmount: function () {
this.off('authChange', this.authChange);
this.authChange = null;
}
Обратите внимание, что когда я увидел this.on
, я подумал, что вы, возможно, используете jQuery, но неясно, как это могло бы быть в случае. В моем ответе используется this.off
для отсоединения прослушивателя событий, но вы должны использовать любой соответствующий метод в вашей среде.
Комментарии:
1. Но разве
this
компонент не должен быть помечен как мусор в любом случае, когдаrenderToString()
функция завершена?
Ответ №2:
Я бы перенес вашу функцию в componentDidMount
и добавил очистку на componentWillUnmount
Важно: componentWillMount
вызывается на сервере и клиенте, но componentDidMount
вызывается только на клиенте.
Если вы используете eventListeners
, setInterval
или другие функции, которые необходимо очистить, вставьте их componentDidMount
. Сервер не выполняет вызов componentWillUnmount
и обычно является причиной утечек памяти.