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的时候报了如上错误,完整信息如下:
造成的原因:组件在卸载之后(比如你切换路由卸载一些组件)依然去更新了state。这里可能是setState,当然也可能是在useState里面的setState(一样的)
两种情况:
- 设置了定时器setinterval 或者递归setTimeout。 组件在之前没有清除掉。
- 异步请求
callback
在请求回来之前组件已经被卸载掉了
解决办法
1. 对于定时器
在componentWillUnmount
生命周期, 必须clear调用定时器
2.对于异步请求
两种解决方案。
- 设置标志位在挂载是为true,
componentWillUnmount
时设为false,然后在异步调用的callback里面做判断 - 在
componentWillUnmount
取消异步请求
这里来一个我自己的栗子,其中使用了定时器和数据请求,当切换路由卸载组件时报了上面的错误:
const [items,setItems] = useState([123,456]);
useEffect(_=>{
let ignore = false;
async function fetchData(){
let res = await post('situationIndex3!getStaffData.action');
res = res.data;
if(!ignore) setItems(res);
}
(function dataTimeInterval(){
setTimeout(_=>{
fetchData();
dataTimeInterval();
},1000)
})()
return _=>{
ignore = true;
}
},[]);
return (...)
这里再useEffect中设置了一个是否不在渲染的flag(ignore)。如果ignore为false,这更新state,如果为true则不再更新state。当组件卸载的时候,将ignore设置为true,即当异步请求回来的时候组件已经卸载了,但是判定为true就不会更新state。
另外注意因为我每隔一秒去请求一次数据,为了避免每次更新都执行effet,这里useEffet的依赖项为[]即选然后只执行一次effect。