我想检索与用户位置相关的产品列表,为此我使用Geofirestore并更新我的Flatlist
当我有前10个最接近的集合时,我循环得到每个子集合。
我设法更新我的状态,但每次我的集合在其他地方被修改,而不是更新我的列表,它复制了我已经修改的对象,并在我的列表的末尾添加它(更新),并保留旧对象在该列表中。
例如:
const listListeningEvents = {
A: {Albert, Ducon}
B: {Mickael}
}
另一个用户修改了'A'并删除了'Ducon',我将得到:
const listListeningEvents = {
A: {Albert, Ducon},
B: {Mickael},
A: {Albert}
}
而不是:
const listListeningEvents = {
A: {Albert},
B: {Mickael},
}
这是我的使用效果:
useEffect(() => {
let geoSubscriber;
let productsSubscriber;
// 1. getting user's location
getUserLocation()
// 2. then calling geoSubscriber to get the 10 nearest collections
.then((location) => geoSubscriber(location.coords))
.catch((e) => {
throw new Error(e.message);
});
//Here
geoSubscriber = async (coords) => {
let nearbyGeocollections = await geocollection
.limit(10)
.near({
center: new firestore.GeoPoint(coords.latitude, coords.longitude),
radius: 50,
})
.get();
// Empty array for loop
let nearbyUsers = [];
// 3. Getting Subcollections by looping onto the 10 collections queried by Geofirestore
productsSubscriber = await nearbyGeocollections.forEach((geo) => {
if (geo.id !== user.uid) {
firestore()
.collection("PRODUCTS")
.doc(geo.id)
.collection("USER_PRODUCTS")
.orderBy("createdDate", "desc")
.onSnapshot((product) => {
// 4. Pushing each result (and I guess the issue is here!)
nearbyUsers.push({
id: product.docs[0].id.toString(),
products: product.docs,
});
});
}
});
setLoading(false);
// 4. Setting my state which will be used within my Flatlist
setListOfProducts(nearbyUsers);
};
return () => {
if (geoSubscriber && productsSubscriber) {
geoSubscriber.remove();
productsSubscriber.remove();
}
};
}, []);
多年来我一直在努力使它正常工作,我快疯了。
所以我梦到了两件事:
- 能够在不复制修改对象的情况下更新我的状态
- (奖励)当我向下滚动到我的Flatlist时,找到一种方法来获得下一个最近的10个点。
在我看来,问题在于nearbyUsers
的类型。它被初始化为数组=[]
,当你将其他对象推入它时,只需在末尾添加新项(数组引用)。
在这种情况下,数组不是很方便,因为要实现目标,需要检查数组中的每个现有项目,并找到是否有适当的id
更新它。
我认为在这种情况下最方便的将是Map
(地图参考)。Map按键索引,因此可以只获取特定的值而不搜索它。
我将尝试调整它以呈现代码(不是所有行,只是更改):
- 修改键为
id
值为products
的映射对象类型:
let nearbyUsersMap = new Map();
- 使用
set
方法代替push
方法更新特定密钥的产品:
nearbyUsersMap.set(product.docs[0].id.toString(), product.docs);
- 最后将Map转换为Array以实现在进一步代码中使用的相同对象:
let nearbyUsers = Array.from(nearbyUsersMap, ([id, products]) => ({ id, products }));
setListOfProducts(nearbyUsers);
这应该工作,但我没有任何游乐场来测试它。如果出现任何错误,请尝试解决它们。我对geofirestore不是很熟悉,所以我不能帮助你更多。当然,还有其他方法可以实现目标,但是这应该在本文中工作,并且只需要进行一些更改。