在 for 循环中使用 firebase onSnapshot()?
Use firebase onSnapshot() in for loop?
下面的代码适用于从 firestore 获取我的数据。我正在尝试将其更新为使用 onSnapshot()
而不是 get()
。也许我的困惑的核心是 onSnapshot()
没有 return 承诺,我试过将侦听器添加到数组中,但数据似乎没有得到更新。如何迭代 onSnapshot()
的 for
循环并呈现结果?
const [activityDataArray, setActivityDataArray] = useState([]);
const userActivityIds = userData.activities
useEffect(() => {
let promises = [];
for (const activityId of userActivityIds) {
promises.push(getFirestoreData("activities", activityId));
}
Promise.all(promises).then(response => setActivityDataArray(response));
}, [userActivityIds]);
更新代码:
当我 console.log()
数组有我的数据时,但我认为这是 chrome 显示新信息的开发工具的一个技巧。我想当我调用 setActivityDataArray
时,它是 运行 它在一个空数组上,然后它再也不会被调用。因此,除非我切换到我的应用程序中的不同选项卡并返回,否则数据不会呈现。然后它正确呈现(所以我知道数据很好,这只是一个呈现问题)。我想我需要在 onSnapshot()
内重新渲染,但我该如何正确地执行此操作?
const [activityDataArray, setActivityDataArray] = useState<any>([]);
const userActivityIds: string[] = userData.activities
useEffect(() => {
let activityDataArrayDummy: any[] = []
for (const i in userActivityIds) {
firebase.firestore().collection("activities").doc(userActivityIds[i])
.onSnapshot((doc) => {
activityDataArrayDummy[i] = doc.data();
});
}
console.log("activityDataArrayDummy", activityDataArrayDummy)
setActivityDataArray(activityDataArrayDummy);
}, [userActivityIds]);
只需在循环中调用 onSnapshot()
即可。
import { doc, onSnapshot } from "firebase/firestore";
for (const activityId of userActivityIds) {
// get reference to document
const docRef = doc(db, "activities", activityId)
onSnapshot(docRef, (snapshot) => {
// read and render data from snapshot
})
}
但是,如果您需要取消订阅任何听众,那么您可能需要存储 Unsubscribe
function returned by onSnapshot
州内某处。
以防万一 userActivityIds
中的项目不超过 10 个,那么您可以使用 onSnapshot()
和 Query
代替:
const q = query(collection(db, "activities"), where(documentId(), "in", userActivityIds));
onSnapshot(q, (querySnapshot) => {
// ...
})
我同意了。显然不能保证反应中的状态会被更新,因此使用更新数据设置状态的正确方法是使用回调函数。
https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
const [activityDataObj, setActivityDataObj] = useState({})
const userActivityIds: string[] = userData.activities
useEffect(() => {
for (const i in userActivityIds) {
firebase.firestore().collection("activities").doc(userActivityIds[i])
.onSnapshot((doc) => {
setActivityDataObj((activityDataObj) => {
return {...activityDataObj, [userActivityIds[i]]: doc.data()}
})
});
}
}, [userActivityIds]);
下面的代码适用于从 firestore 获取我的数据。我正在尝试将其更新为使用 onSnapshot()
而不是 get()
。也许我的困惑的核心是 onSnapshot()
没有 return 承诺,我试过将侦听器添加到数组中,但数据似乎没有得到更新。如何迭代 onSnapshot()
的 for
循环并呈现结果?
const [activityDataArray, setActivityDataArray] = useState([]);
const userActivityIds = userData.activities
useEffect(() => {
let promises = [];
for (const activityId of userActivityIds) {
promises.push(getFirestoreData("activities", activityId));
}
Promise.all(promises).then(response => setActivityDataArray(response));
}, [userActivityIds]);
更新代码:
当我 console.log()
数组有我的数据时,但我认为这是 chrome 显示新信息的开发工具的一个技巧。我想当我调用 setActivityDataArray
时,它是 运行 它在一个空数组上,然后它再也不会被调用。因此,除非我切换到我的应用程序中的不同选项卡并返回,否则数据不会呈现。然后它正确呈现(所以我知道数据很好,这只是一个呈现问题)。我想我需要在 onSnapshot()
内重新渲染,但我该如何正确地执行此操作?
const [activityDataArray, setActivityDataArray] = useState<any>([]);
const userActivityIds: string[] = userData.activities
useEffect(() => {
let activityDataArrayDummy: any[] = []
for (const i in userActivityIds) {
firebase.firestore().collection("activities").doc(userActivityIds[i])
.onSnapshot((doc) => {
activityDataArrayDummy[i] = doc.data();
});
}
console.log("activityDataArrayDummy", activityDataArrayDummy)
setActivityDataArray(activityDataArrayDummy);
}, [userActivityIds]);
只需在循环中调用 onSnapshot()
即可。
import { doc, onSnapshot } from "firebase/firestore";
for (const activityId of userActivityIds) {
// get reference to document
const docRef = doc(db, "activities", activityId)
onSnapshot(docRef, (snapshot) => {
// read and render data from snapshot
})
}
但是,如果您需要取消订阅任何听众,那么您可能需要存储 Unsubscribe
function returned by onSnapshot
州内某处。
以防万一 userActivityIds
中的项目不超过 10 个,那么您可以使用 onSnapshot()
和 Query
代替:
const q = query(collection(db, "activities"), where(documentId(), "in", userActivityIds));
onSnapshot(q, (querySnapshot) => {
// ...
})
我同意了。显然不能保证反应中的状态会被更新,因此使用更新数据设置状态的正确方法是使用回调函数。
https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
const [activityDataObj, setActivityDataObj] = useState({})
const userActivityIds: string[] = userData.activities
useEffect(() => {
for (const i in userActivityIds) {
firebase.firestore().collection("activities").doc(userActivityIds[i])
.onSnapshot((doc) => {
setActivityDataObj((activityDataObj) => {
return {...activityDataObj, [userActivityIds[i]]: doc.data()}
})
});
}
}, [userActivityIds]);