# #reactjs #firebase #google-cloud-firestore #react-hooks
Вопрос:
Мне любопытно, может ли кто-нибудь помочь мне с моим пользовательским крючком, который прослушивает данные в реальном времени из Firestore.
В некотором контексте пользовательский крючок предназначен для уведомлений, которые должны срабатывать при добавлении нового документа в коллекцию notifications_history пользователя в Firestore. Я хочу, чтобы это были уведомления, которые они действительно получили после того, как отрисовали страницу, поэтому я заказываю их по их временной метке createdAt, и я также проверяю, чтобы они были созданы после временной метки, которую я создаю при первоначальной отрисовке. (Для этого я использую крючок useRef)
Пользовательский хук имеет эффект использования, для которого требуется идентификатор пользователя, прошедшего проверку подлинности, и я не смог придумать никакого другого решения, кроме добавления идентификатора uid в массив зависимостей эффекта использования, поскольку пользователь изначально не определен. Однако я не могу избавиться от ощущения, что делаю что-то не так, и что есть лучшее решение.
Одна из моих проблем заключается в том, что, поскольку эффект использования имеет пользователя в качестве зависимости, то, возможно, это может создать несколько прослушивателей в случае возникновения некоторых проблем с аутентификацией?
Еще одна моя проблема, которая, как я полагаю, связана с реакцией, заключается в том, могу ли я каким-либо образом сделать так, чтобы я передавал uid в качестве опоры для крючка только тогда, когда на самом деле есть uid? Это действительно решило бы вышеперечисленные проблемы так!
Вот код:
import { useEffect, useRef, useState } from "react";
import { clientFirestore } from "@/frontend/client/firebase";
import {
collection,
query,
limit,
orderBy,
where,
onSnapshot,
} from "firebase/firestore";
import { useAuth } from "./useAuth";
const useNotification = () => {
const timeRef = useRef(Date.now());
const { user } = useAuth();
const uid = user?.uid;
const [data, setData] = useState({
error: null,
loading: true,
notification: null,
});
useEffect(() => {
if (!uid) return;
const notificationQuery = query(
collection(clientFirestore, `users/${uid}/notification_history`),
orderBy("createdAt"),
where("createdAt", ">=", timeRef.current),
limit(1)
);
const unsubscribe = onSnapshot(
notificationQuery,
(snapshot) => {
let newNotification;
snapshot.forEach((doc) => {
const docData = doc.data();
if (doc amp;amp; docData) {
newNotification = {
id: doc.id,
message: docData.message,
createdAt: docData.createdAt,
};
}
});
setData({
error: null,
loading: false,
notification: newNotification,
});
},
(error) => {
setData({
error,
loading: false,
notification: null,
});
console.log(error);
}
);
return unsubscribe;
}, [uid]);
return data;
};
export default useNotification;
.
.
.
in another file:
const data = useNotification();
useEffect(() => {
if (data amp;amp; data.notification) {
toast.success(data.notification.message);
playSound();
}
}, [data]);