kus*_*sha 6 reactjs react-context react-hooks use-effect
每次onClick执行时,我都会收到一条关于内存泄漏的警告消息。如何使用钩子从我的功能组件中的Context.Consumer取消订阅组件useEffect?
我没有找到如何取消订阅 AppContext 的方法。AppContext.unsubsribe()不工作。
import React, {useState, useContext} from 'react';
import {withRouter} from 'react-router-dom';
import axios from 'axios';
import {AppContext} from "../context/AppContext";
const LoginPage = (props) => {
const [name, setName] = useContext(AppContext);
const [isLoading, setIsLoading] = useState(false);
const onClick = () => {
setIsLoading(true);
axios.post('/get-name')
.then(resp => {
setName(resp);
setIsLoading(false);
props.history.push('/');
})
.catch(err => console.log(err))
.finally(() => setIsLoading(false));
};
return (
<div>
<button onClick={onClick}></button>
</div>
);
};
export default withRouter(LoginPage);
Run Code Online (Sandbox Code Playgroud)
浏览器控制台中的错误消息:
警告:无法对卸载的
组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要修复,请取消 useEffect 清理函数中的所有订阅和异步任务。在UserPage(由Context.Consumer创建)在Route(由withRouter(UserPage)创建)在withRouter(LoginPage)(由Context.Consumer创建)在Route(由UserRoute创建)
您的问题是 axios 返回一个承诺,因此当安装组件时,它会axios.post(...)在单击时执行。当它然后卸载时(虽然承诺仍可能“未完成”),其setState将finally在组件卸载后执行。
您可以使用简单的方法检查组件是否已安装:
import React, {useState, useContext, useEffect} from 'react';
import {withRouter} from 'react-router-dom';
import axios from 'axios';
import {AppContext} from "../context/AppContext";
const LoginPage = (props) => {
const [name, setName] = useContext(AppContext);
const [isLoading, setIsLoading] = useState(false);
const isMounted = useRef(null);
useEffect(() => {
// executed when component mounted
isMounted.current = true;
return () => {
// executed when unmount
isMounted.current = false;
}
}, []);
const onClick = () => {
setIsLoading(true);
axios.post('/get-name')
.then(resp => {
setName(resp);
setIsLoading(false);
props.history.push('/');
})
.catch(err => console.log(err))
.finally(() => {
if (isMounted.current) {
setIsLoading(false)
}
});
};
return (
<div>
<button onClick={onClick}></button>
</div>
);
};
export default withRouter(LoginPage);
Run Code Online (Sandbox Code Playgroud)
正如警告所述,在您的UserPage组件中,您需要执行清理useEffect以避免内存泄漏。
请参阅文档如何在效果后要求清理。
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
return () => {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
13430 次 |
| 最近记录: |