#reactjs #firebase #google-cloud-firestore #react-big-calendar
#reactjs #firebase #google-облако-firestore #react-big-calendar
Вопрос:
В настоящее время я пытаюсь заставить React-Big-Calendar заполнять недавно добавленное событие в режиме реального времени. Я использую приведенный ниже код, и он выполняет свою работу. События будут добавлены в календарь сразу после его создания / изменения / удаления. Однако он выполняет чтение, даже если я не добавляю или не удаляю событие из календаря. В течение 5 минут после запуска календаря я превысил свой дневной лимит в 50 тыс. чтений из Firestore. Правильно ли я использую подход?Моя цель — обновить календарь без обновления при добавлении / изменении / удалении нового события. Есть ли способ обновлять календарь только при изменении / обновлении?Когда I console.log(snapshot.docChanges())
, он возвращает данные, и все типы added
независимо от того, являются ли они старыми данными, поскольку они не были добавлены недавно. Это нормально?
Кроме того, я не слишком уверен в том, как и когда использовать эту unsubscribe()
функцию. Когда я должен его вызывать?Поправьте меня, если я ошибаюсь, но прямо сейчас, возвращаясь unsubscribe()
в конце, предполагается, что он будет действовать как componentWillUnmount .
//events are used in calendar
const [events, setEvents] = useState([] as CalendarEvent[]);
//onSnapshot to check for real-time updates
useEffect(() => {
const unsubscribe = firebase
.firestore()
.collectionGroup("bookings")
.where("orgId", "==", props.orgId ? props.orgId : null)
.onSnapshot((snapshot) => {
const bookedEvents: any = [];
snapshot.forEach((doc) => bookedEvents.push({ ...doc.doc.data() }));
//creates an eventlist so the calendar can call individual events
const eventList = bookedEvents.map((event: any) => {
return {
title: event.title,
start: new Date(
moment(event.time.startTime * 1000).format("YYYY-MM-DD HH:mm:ss")
),
end: new Date(
moment(event.time.endTime * 1000).format("YYYY-MM-DD HH:mm:ss")
),
eventId: event.eventId,
name: event.participants.name,
email: event.participants.email,
phoneNumber: event.phoneNumber,
itemQuantity: event.itemQuantity,
memberBookingType: event.memberBookingType,
};
});
//sets the eventlist as events for calendar
setEvents(eventList as CalendarEvent[]);
});
//componentWillUnmount unsubscribe();
return () => {
unsubscribe();
};
});
Ответ №1:
У вас нет определенного списка зависимостей useEffect
, поэтому он, вероятно, запускается повторно при каждом повторном запуске компонента. И, поскольку он выполняет «первый» вызов при каждом запуске…
Вы хотите, чтобы он подписывался только при монтировании и отменял подписку при размонтировании. В документации React hooks есть довольно четкие примеры именно этого, предоставляя пустой массив зависимостей.
useEffect(() => {
const unsubscribe = subscribe(); // paraphrasing here
return () => {
unsubscribe();
};
}, []};
Если подписка возвращает все события каждый раз, когда происходит изменение, то вызов setEvents
с полным массивом приведет к повторному отображению каждого события, а не только тех, которые были изменены. Это может быть то, что вы хотите.
Кроме того, вы также можете использовать деструктурирование в своем .map()
коде, чтобы упростить свой код.
const eventList = bookedEvents.map((event: any) => {
const {time: {startTime, endTime}, ...thisEvent} = event;
return {
...thisEvent,
start: new Date(
moment(startTime * 1000).format("YYYY-MM-DD HH:mm:ss")
),
end: new Date(
moment(endTime * 1000).format("YYYY-MM-DD HH:mm:ss")
),
};
});