我正在使用 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
是一個承諾,因為它getChat
是異步的,但我仍然想getUserData()
在調用 onSnapShot 之前等待,因為稍後我將需要 onSnapShot 查詢中的用戶數據。
有沒有辦法使這項工作能夠unsubscribe
在 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
鉤子回調主體中添加一個額外的異步函數,它可以等待getChat
Promise 解析。
useEffect(() => {
let unsubscribe;
const getChatAndSubscribe = async () => {
unsubscribe = await getChat();
}
getChatAndSubscribe();
return () => {
unsubscribe?.();
};
}, []);
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句