react 內存洩露常見問題解決方案

react 內存洩露常見問題解決方案

什麼是內存洩露

  • 程序的運行需要內存。只要程序提出要求,操作系統或者運行時(runtime)就必須供給內存。
  • 對於持續運行的服務進程(daemon),必須及時釋放不再用到的內存。否則,內存佔用越來越高,輕則影響系統性能,重則導致進程崩潰。
  • 不再用到的內存,沒有及時釋放,就叫做內存洩漏(memory leak)。

JavaScript 中常見的幾種內存洩露

  • 全局變量引起的內存洩漏
function leaks(){ 
leak = '***'; //leak 成為一個全局變量,不會被回收
}
  • 閉包引起的內存洩漏
var leaks = (function(){ 
var leak = '***';// 被閉包所引用,不會被回收
return function(){
console.log(leak);
}

})()
  • dom清空或刪除時,事件未清除導致的內存洩漏
document.querySelector("#demo").addEventListener('click', myFunction);
var para1=document.querySelector("#demo");
para1.parentNode.removeChild(para1);

如果我們在沒有取消 click 方法前去銷燬了 para1 節點,就會造成內存洩露。

正確的做法:

document.querySelector("#demo").addEventListener('click', myFunction);
// 我們需要在刪除節點前清除掛載的 click 方法
document.querySelector("#demo").removeEventListener("click", myFunction);
var para1=document.querySelector("p1");
para1.parentNode.removeChild(para1);

具體的示例

Demo1:

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));
}

上面的例子是在 Stack Overflow 上看到的,樓主在componentWillMount的時候掛載了authChange事件,然後 react 出現瞭如下的報錯:

Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method”

意思為:我們不能在組件銷燬後設置state,防止出現內存洩漏的情況

需要怎麼解決啦?

添加如下代碼即可

 componentWillUnmount: function () {
this.off('authChange', this.authChange);
this.authChange = null;
}

很明顯這種情況就是在 dom 結構銷燬的時候,事件卻沒有清除導致的內存洩漏,所以我們需要在componentWillUnmount的時候去清除掛載的方法

react 內存洩露相關解釋和解決方法

這裡就提到了內存洩露,當我們在使用事件綁定,setInterval,setTimeOut 或一些函數的時候,但是卻沒有在組件銷燬前清除的時候會造成內存洩露。這裡我們手動的再componentWillUnmount去清除相關的方法即可。

Demo 2

下面這種就是常見的情況:

this.pwdErrorTimer = setTimeout(() => {
this.setState({
showPwdError:false
})
}, 1000);

設置了一個timer延遲設置state,然而在延遲的這段時間,組件已經銷燬,則造成此類問題

解決方法:

利用生命週期鉤子函數:componentWillUnmount

componentWillUnmount(){
clearTimeout(this.pwdErrorTimer);
clearTimeout(this.userNameErrorTimer);
}


分享到:


相關文章: