React內(nèi)存泄露常見問題解決方案
什么是內(nèi)存泄露
- 程序的運行需要內(nèi)存。只要程序提出要求,操作系統(tǒng)或者運行時(runtime)就必須供給內(nèi)存。
- 對于持續(xù)運行的服務(wù)進(jìn)程(daemon),必須及時釋放不再用到的內(nèi)存。否則,內(nèi)存占用越來越高,輕則影響系統(tǒng)性能,重則導(dǎo)致進(jìn)程崩潰。
- 不再用到的內(nèi)存,沒有及時釋放,就叫做內(nèi)存泄漏(memory leak)。
JavaScript 中常見的幾種內(nèi)存泄露
- 全局變量引起的內(nèi)存泄漏
- function leaks(){
- leak = '***'; //leak 成為一個全局變量,不會被回收
- }
- var leaks = (function(){
- var leak = '***';// 被閉包所引用,不會被回收
- return function(){
- console.log(leak);
- }
- })()
- document.querySelector("#demo").addEventListener('click', myFunction);
- var para1=document.querySelector("#demo");
- para1.parentNode.removeChild(para1);
如果我們在沒有取消 click 方法前去銷毀了 para1 節(jié)點,就會造成內(nèi)存泄露。
正確的做法:
- document.querySelector("#demo").addEventListener('click', myFunction);
- // 我們需要在刪除節(jié)點前清除掛載的 click 方法
- document.querySelector("#demo").removeEventListener("click", myFunction);
- var para1=document.querySelector("p1");
- para1.parentNode.removeChild(para1);
具體的示例
1. 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 出現(xiàn)了如下的報錯:
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 |
意思為:我們不能在組件銷毀后設(shè)置state,防止出現(xiàn)內(nèi)存泄漏的情況
(1) 需要怎么解決啦?
添加如下代碼即可:
- componentWillUnmount: function () {
- this.off('authChange', this.authChange);
- this.authChange = null;
- }
很明顯這種情況就是在 dom 結(jié)構(gòu)銷毀的時候,事件卻沒有清除導(dǎo)致的內(nèi)存泄漏,所以我們需要在componentWillUnmount的時候去清除掛載的方法
(2) react 內(nèi)存泄露相關(guān)解釋和解決方法
這里就提到了內(nèi)存泄露,當(dāng)我們在使用事件綁定,setInterval,setTimeOut 或一些函數(shù)的時候,但是卻沒有在組件銷毀前清除的時候會造成內(nèi)存泄露。這里我們手動的再componentWillUnmount去清除相關(guān)的方法即可。
2. Demo 2
下面這種就是常見的情況:
- this.pwdErrorTimer = setTimeout(() => {
- this.setState({
- showPwdError:false
- })
- }, 1000);
設(shè)置了一個timer延遲設(shè)置state,然而在延遲的這段時間,組件已經(jīng)銷毀,則造成此類問題
解決方法:
利用生命周期鉤子函數(shù):componentWillUnmount
- componentWillUnmount(){
- clearTimeout(this.pwdErrorTimer);
- clearTimeout(this.userNameErrorTimer);
- }