面试题答案
一键面试可能出现内存泄漏的生命周期阶段及避免方法
- componentDidMount
- 原因:在此阶段常进行一些副作用操作,如订阅事件、设置定时器等,如果在组件卸载时没有清理,就会导致内存泄漏。
- 避免代码示例:
import React, { Component } from'react';
class MyComponent extends Component {
constructor(props) {
super(props);
this.handleScroll = this.handleScroll.bind(this);
}
componentDidMount() {
window.addEventListener('scroll', this.handleScroll);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll);
}
handleScroll() {
// 处理滚动事件的逻辑
}
render() {
return <div>My Component</div>;
}
}
export default MyComponent;
- componentDidUpdate
- 原因:如果在此阶段设置了定时器或订阅了事件,且没有在适当的时候清理,同样会引发内存泄漏。例如,每次更新都创建新的定时器而不清除旧的。
- 避免代码示例:
import React, { Component } from'react';
class UpdateComponent extends Component {
constructor(props) {
super(props);
this.timer = null;
}
componentDidUpdate(prevProps, prevState) {
if (prevProps.someProp!== this.props.someProp) {
if (this.timer) {
clearInterval(this.timer);
}
this.timer = setInterval(() => {
// 定时器逻辑
}, 1000);
}
}
componentWillUnmount() {
if (this.timer) {
clearInterval(this.timer);
}
}
render() {
return <div>Update Component</div>;
}
}
export default UpdateComponent;
- 使用第三方库的回调注册
- 原因:在组件中使用第三方库,可能会注册一些回调函数,如果在组件卸载时没有反注册这些回调,会导致内存泄漏。例如使用
google - maps - api
注册的地图事件回调。 - 避免代码示例:假设使用Google Maps API
- 原因:在组件中使用第三方库,可能会注册一些回调函数,如果在组件卸载时没有反注册这些回调,会导致内存泄漏。例如使用
import React, { Component } from'react';
class MapComponent extends Component {
constructor(props) {
super(props);
this.map = null;
this.mapListener = null;
}
componentDidMount() {
const mapOptions = {
center: { lat: 0, lng: 0 },
zoom: 8
};
this.map = new window.google.maps.Map(document.getElementById('map'), mapOptions);
this.mapListener = window.google.maps.event.addListener(this.map, 'click', () => {
// 地图点击事件逻辑
});
}
componentWillUnmount() {
if (this.mapListener) {
window.google.maps.event.removeListener(this.mapListener);
}
}
render() {
return <div id="map" style={{ height: '400px' }}></div>;
}
}
export default MapComponent;
在React新的 hooks
写法中,useEffect
可以替代上述生命周期方法。使用 useEffect
时,返回一个清理函数来避免内存泄漏。例如:
import React, { useEffect } from'react';
const MyHookComponent = () => {
useEffect(() => {
const handleScroll = () => {
// 处理滚动事件逻辑
};
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
return <div>Hook Component</div>;
};
export default MyHookComponent;