【问题标题】:Multiple Firebase listeners in useEffect and pushing new event into stateuseEffect 中的多个 Firebase 侦听器并将新事件推送到状态
【发布时间】:2021-03-04 11:49:46
【问题描述】:

我想检索与用户位置相关的产品列表,为此我使用 Geofirestore 并更新我的平面列表

当我拥有前 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:

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();
    }
  };
}, []);

多年来,我一直在努力使其正常工作,我快要疯了。

所以我梦想着两件事:

  1. 能够在不复制修改对象的情况下更新我的状态。
  2. (奖励)当我向下滚动到平面列表时,找到一种方法来获取下一个最近的 10 个点。

【问题讨论】:

    标签: javascript reactjs firebase react-native google-cloud-firestore


    【解决方案1】:

    在我看来,问题在于nearbyUsers 的类型。它被初始化为数组=[],当您将其他对象推送到它时,只需在末尾添加新项目(array reference)。

    在这种情况下,Array 不是很方便,因为要实现目标,需要检查 Array 中的每个现有项,并查找是否找到正确的 id 更新它。

    我认为在这种情况下最方便的是Map (Map reference)。 Map 按键索引,因此无需搜索即可获得特定值。

    我将尝试将其调整为呈现的代码(不是所有行,只是更改):

    1. 更改用于映射的对象类型,其中键为id,值为products
    let nearbyUsersMap =  new Map();
    
    1. 使用set 方法而不是push 来更新具有特定密钥的产品:
     nearbyUsersMap.set(product.docs[0].id.toString(), product.docs);
    
    1. 最后将 Map 转换为 Array 以实现相同的对象,以便在进一步的代码中使用 (taken from here):
    let nearbyUsers = Array.from(nearbyUsersMap,  ([id, products]) => ({ id, products }));
    setListOfProducts(nearbyUsers);
    

    这应该可以,但我没有任何游乐场可以测试它。如果您遇到任何错误,请尝试解决它们。我对 geofirestore 不是很熟悉,所以我无法为您提供更多帮助。当然还有其他方法可以实现这个目标,但是这应该可以在呈现的代码中工作,并且只有很少的变化。

    【讨论】:

    • 谢谢,我就是这么做的。
    猜你喜欢
    • 2021-07-18
    • 1970-01-01
    • 2021-03-10
    • 2022-10-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-09
    • 2023-02-26
    • 1970-01-01
    相关资源
    最近更新 更多