gpt4 book ai didi

reactjs - 取消 useEffect Hook 中的所有异步/等待任务以防止 react 中内存泄漏的正确方法是什么?

转载 作者:行者123 更新时间:2023-12-03 13:42:36 24 4
gpt4 key购买 nike

我正在开发一个 React chap 应用程序,该应用程序从 Firebase 数据库中提取数据。在我的“仪表板”组件中,我有一个 useEffect Hook 检查经过身份验证的用户,如果是这样,则从 firebase 中提取数据并设置电子邮件变量和聊天变量的状态。我使用 abortController 进行 useEffect 清理,但是每当我第一次注销并重新登录时,我都会收到内存泄漏警告。

index.js:1375 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.

in Dashboard (created by Context.Consumer)

本来我没有abortController,我只是返回了一个清理控制台日志。做了更多研究并发现 abortController 但是示例使用 fetch 和 signal,我找不到任何有关使用 async/await 的资源。我愿意改变数据的检索方式(无论是使用 fetch、async/await 还是任何其他解决方案),我只是无法让它与其他方法一起使用。

const [email, setEmail] = useState(null);
const [chats, setChats] = useState([]);

const signOut = () => {
firebase.auth().signOut();
};

useEffect(() => {
const abortController = new AbortController();
firebase.auth().onAuthStateChanged(async _user => {
if (!_user) {
history.push('/login');
} else {
await firebase
.firestore()
.collection('chats')
.where('users', 'array-contains', _user.email)
.onSnapshot(async res => {
const chatsMap = res.docs.map(_doc => _doc.data());
console.log('res:', res.docs);
await setEmail(_user.email);
await setChats(chatsMap);
});
}
});

return () => {
abortController.abort();
console.log('aborting...');
};
}, [history, setEmail, setChats]);

预期结果是在 useEffect 清理函数中正确清理/取消所有异步任务。一个用户注销后,相同或不同的用户重新登录后,我在控制台中收到以下警告

index.js:1375 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.

in Dashboard (created by Context.Consumer)

最佳答案

对于firebase,您处理的不是async/await而是流。您应该在清理功能中取消订阅 Firebase 流:

const [email, setEmail] = useState(null);
const [chats, setChats] = useState([]);

const signOut = () => {
firebase.auth().signOut();
};

useEffect(() => {
let unsubscribeSnapshot;
const unsubscribeAuth = firebase.auth().onAuthStateChanged(_user => {
// you're not dealing with promises but streams so async/await is not needed here
if (!_user) {
history.push('/login');
} else {
unsubscribeSnapshot = firebase
.firestore()
.collection('chats')
.where('users', 'array-contains', _user.email)
.onSnapshot(res => {
const chatsMap = res.docs.map(_doc => _doc.data());
console.log('res:', res.docs);
setEmail(_user.email);
setChats(chatsMap);
});
}
});

return () => {
unsubscribeAuth();
unsubscribeSnapshot && unsubscribeSnapshot();
};
}, [history]); // setters are stable between renders so you don't have to put them here

关于reactjs - 取消 useEffect Hook 中的所有异步/等待任务以防止 react 中内存泄漏的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58562474/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com