用React写了一段代码,浏览器的控制台Error 如下:
Warning: 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 a useEffect cleanup function.
啥意思呢:不能在未挂载的组件上执行React状态更新。这是一个无用功,但它表明你的应用程序中存在内存泄漏。要解决这个问题,在useEffect清理函数中取消所有的订阅和异步任务。
以下是这段问题代码:
1 | const Component = (props) => { |
原因是啥呢:await等待一个异步请求的返回再setIsRemoveing
。假如这个组件unmounted之后,请求还没回来,你还在这setState,不就炸了。
好吧,那解决方式是不是在useEffect
中定义一个卸载时的变量unmounted
,然后在setIsRemoveing时判断卸载状态?
嗯,基本是这个思路。那这个unmounted
该怎么定义,是直接const unmounted = false;
, 还是const [ unmounted, setUnmounted ] = useState(false);
?
以下是Stack Overflow里一个帖子的回复:
- 方式一:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19useEffect(() => {
let unmounted = false;
setPageLoading(true);
props
.dispatch(fetchCourses())
.then(() => {
if (!unmounted) {
setPageLoading(false);
}
})
.catch((error: string) => {
if (!unmounted) {
toast.error(error);
setPageLoading(false);
}
});
return () => { unmounted = true };
}, []); - 方式二:useRef
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20const Example = (props) => {
const unmounted = useRef(false);
useEffect(() => {
return () => { unmounted.current = true }
}, []);
const setFilter = () => {
// ...
props.dispatch(fetchCourses()).then(() => {
if (!unmounted.current) {
setLoading(false);
}
})
}
// ...
return (
<ReactTable onFetchData={setFilter} /* other props omitted */ />
);
}
方式二中如果不用ref,用state或者直接定义变量的话,都实现不了。
好吧,是我不熟悉的useRef,这个链接是官方文档,可以先看下。
然后为了研究它,我找到一篇来自Lee Warrick的React’s useEffect and useRef Explained for Mortals。这里是我对这篇文章的翻译,仅供参考。
参考
React Hooks - Check If A Component Is Mounted
how-to-stop-memory-leak-in-useeffect-hook-react
- 本文标题:React-防止内存泄漏处理
- 本文作者:乔文飞
- 创建时间:2021-06-18 13:40:49
- 本文链接:http://www.feidom.com/2021/06/18/React-防止内存泄漏处理/
- 版权声明:本博客所有文章为作者学习笔记,有转载其他前端大佬的文章。转载时请注明出处。