面试题答案
一键面试可能出现内存泄漏的场景
- 异步操作未清理:
- 例如在
useEffect
模拟componentDidMount
时发起一个fetch
请求:
import React, { useEffect } from'react'; const MyComponent = () => { useEffect(() => { const controller = new AbortController(); const signal = controller.signal; fetch('https://example.com/api/data', { signal }) .then(response => response.json()) .then(data => console.log(data)); return () => { controller.abort(); }; }, []); return <div>My Component</div>; }; export default MyComponent;
- 如果没有在
useEffect
返回的清理函数中取消这个fetch
请求(即controller.abort()
),当组件卸载时,这个fetch
请求可能仍在后台执行,占用资源,造成内存泄漏。
- 例如在
- 事件监听未移除:
- 假设在
useEffect
模拟componentDidMount
时添加一个全局事件监听:
import React, { useEffect } from'react'; const MyComponent = () => { useEffect(() => { const handleScroll = () => { console.log('Window scrolled'); }; window.addEventListener('scroll', handleScroll); return () => { window.removeEventListener('scroll', handleScroll); }; }, []); return <div>My Component</div>; }; export default MyComponent;
- 如果没有在清理函数中移除这个事件监听(即
window.removeEventListener('scroll', handleScroll)
),即使组件已经卸载,handleScroll
函数仍然会被调用,占用内存,导致内存泄漏。
- 假设在
避免内存泄漏的方法
- 清理异步操作:
- 对于
fetch
请求等异步操作,使用AbortController
来取消操作。如上面第一个例子,在useEffect
返回的清理函数中调用controller.abort()
,确保在组件卸载时取消未完成的请求。
- 对于
- 移除事件监听:
- 对于添加的事件监听,在
useEffect
返回的清理函数中使用相应的移除方法。如在添加window.addEventListener
后,在清理函数中使用window.removeEventListener
移除监听,确保组件卸载时不再响应这些事件,避免内存泄漏。
- 对于添加的事件监听,在