我正在使用 Firebase v9,正在构建一个聊天应用,我需要在调用 onSnapShot 获取聊天数据之前执行一些异步工作:
const getChat = async () => {
// I need to await for user data before doing anything else.
// I'll need some user data to build the query which
// I'll be using in onSnapShot later on.
const user = await getUserData();
console.log(user);
const collectionRef = collection(db, "messages");
const q = query(
collectionRef, where("user_id", "==", user.id), orderBy("createdAt"));
const unsubscribe = onSnapshot(q, (snapshot) => {
const data = snapshot.docs.map((doc) => {
const entry = doc.data();
return {
id: doc.id,
message: entry.message,
};
});
setChatLines(data);
});
return unsubscribe;
};
然后在useEffect中:
useEffect(() => {
const unsubscribe = getChat();
return () => {
unsubscribe();
};
}, []);
这里的问题是 unsubsribe
是一个 promise ,因为 getChat
是异步的,但我仍然想在 onSnapShot 之前等待 getUserData()
被调用,因为稍后我将在 onSnapShot 查询中需要用户数据。
有没有办法让这项工作同时能够在 useEffect 清理函数中正确取消订阅
?
最佳答案
在这种情况下,我建议使用 React ref 来保存要在 useEffect
清理函数中使用的取消订阅函数。
const unsubscribeRef = React.useRef();
const getChat = async () => {
const user = await getUserData();
const collectionRef = collection(db, "messages");
const q = query(
collectionRef, where("user_id", "==", user.id), orderBy("createdAt"));
const unsubscribe = onSnapshot(q, (snapshot) => {
const data = snapshot.docs.map((doc) => {
const entry = doc.data();
return {
id: doc.id,
message: entry.message,
};
});
setChatLines(data);
});
unsubscribeRef.current = unsubscribe;
};
useEffect(() => {
getChat();
return () => {
unsubscribeRef.current?.();
};
}, []);
另一种选择是在 useEffect
Hook 回调主体中添加一个额外的异步函数,该函数可以等待 getChat
Promise 解析。
useEffect(() => {
let unsubscribe;
const getChatAndSubscribe = async () => {
unsubscribe = await getChat();
}
getChatAndSubscribe();
return () => {
unsubscribe?.();
};
}, []);
关于reactjs - 在 useEffect React 中调用异步函数中的 Firebase v9 onSnapShot,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69732710/