# #reactjs #firebase #react-native #google-cloud-firestore
Вопрос:
Я хочу использовать свое время в firestore для своего приложения для чата. Я закодировал код ниже, но есть проблема со значением поля firestore.
Я отправляю свое сообщение в firestore, как:
chatsRef.add({
...m,
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
});
Все работает правильно, но когда я слушаю(onSnapshot), документ, в котором указано chatsRef
createdAt
значение, всегда становится нулевым, также когда я проверил, правильно ли установлено время firestore. Я думаю, что там есть асинхронное событие, и я должен его дождаться. Как я могу решить эту проблему?
То chatsRef
:
const chatsRef= db.collection("ChatRooms").doc(id).collection("Chat")
Я слушаю чат с этим кодом:
useEffect(() => {
let x = null;
const unsubscribe = chatsRef
.orderBy("createdAt", "desc")
.limit(10)
.onSnapshot((querySnapshot) => {
const messagesFirestore = querySnapshot
.docChanges()
.filter(({ type }) => type === "added")
.map(({ doc }) => {
const message = doc.data();
x = message;
console.log(x);// I checked my code and the object's createdAt field gets null.
return { ...message, createdAt: message.createdAt.toDate() };
});
appendMessages(messagesFirestore);
// Some irrelevant codes
return () => unsubscribe();
}, []);
Также моя структура JSON сообщения такова :
Object {
"_id": "a51d2e86-df8d-449e-b41e-73fbd746856f",
"createdAt": t {
"nanoseconds": 26000000,
"seconds": 1616336752
},
"text": "1111",
"user": Object {
"_id": "jack1212312",
"name": "jackAndME",
},
}
Последние изменения:
useEffect(() => {
let x = null;
const unsubscribe = chatsRef
.orderBy("createdAt", "desc")
.limit(10)
.onSnapshot({ includeMetadataChanges: true }, (querySnapshot) => {
const messagesFirestore = querySnapshot
.docChanges()
.filter(({ type }) => type === "added")
.map(({ doc }) => {
const message = doc.data();
if (!doc.metadata.hasPendingWrites) {
x = message;
return { ...message, createdAt: message.createdAt.toDate() };
}
return null;
});
if (messagesFirestore[0]) {
appendMessages(messagesFirestore);
if (latestMessage.current != null) {
if (
new Date(
latestMessage.current["createdAt"]["seconds"] * 1000
latestMessage.current["createdAt"]["nanoseconds"] / 1000000
) >
new Date(
x["createdAt"]["seconds"] * 1000
x["createdAt"]["nanoseconds"] / 1000000
)
) {
latestMessage.current = x;
}
} else {
latestMessage.current = x;
}
}
});
return () => unsubscribe();
}, []);
Примечание: Теперь я могу обнаружить метаданные, но не могу получить доступ к последней версии данных с помощью моментального снимка.
Док Firebase говорит, что :
1- A change event is immediately fired with the new data. The document has not yet been written to the backend so the "pending writes" flag is true.
2- The document is written to the backend.
3- The backend notifies the client of the successful write. There is no change to the document data, but there is a metadata change because the "pending writes" flag is now false.
Но я не могу получить доступ к флагу pendingwrites, когда метаданные записываются в бэкэнд без обновления страницы, снимок не получил данные.
Комментарии:
1. Вы уже пытались вызвать функцию с асинхронным ожиданием?
2. Я не понимаю, что вы имеете в виду? Не могли бы вы объяснить немного подробнее? @LaravDev
Ответ №1:
Это связано с тем, что Firebase называет «компенсацией задержки».:
Локальные записи в вашем приложении немедленно вызовут прослушиватели моментальных снимков. Это связано с важной функцией, называемой «компенсация задержки». Когда вы выполняете запись, ваши слушатели будут уведомлены о новых данных до того, как данные будут отправлены в серверную часть.
Ваш моментальный снимок запускается перед выходом из приложения, и поле для отметки времени будет null
, затем он будет активирован снова после достижения серверной части с установленной меткой времени.
Чтобы провести различие между ними, используйте поле metadata.hasPendingWrites
, как описано в документации.
Комментарии:
1. Спасибо за помощь. Теперь я могу обнаружить метаданные, но как я могу получить последнюю версию данных( после написания бэкенда), потому что я могу обнаружить изменение, но не могу получить доступ к данным последней версии. Я также добавил свой последний код. Также я добавил цитату из firebase.
2. Документ «изменен» после достижения серверной части, поэтому удалите фильтрацию «добавленных» документов, и вы увидите его