【问题标题】:Firestore onSnapshot updates and adds array to the DOM instead of only updatingFirestore onSnapshot 更新并将数组添加到 DOM 而不是仅更新
【发布时间】:2019-10-12 15:18:41
【问题描述】:

我有来自 Firestore 的数据,我正在映射到 DOM,然后更新客户端。当数据按照我想要的方式更新时,每次事件触发时,都会将另一个更新的数组添加到 DOM 中。

我认为问题在于点击事件的设置方式,但我不确定如何在阵列上应用我的客户端操作。

这是我的设置和点击事件

function App() {
  const [heroesArr, setHeroesArr] = useState([]);
  const db = firebase.firestore();
  const onFetch = () => {
    const newHeroes = [];
    db.collection("characterOptions").onSnapshot(coll => {
      coll.forEach(doc => {
        const { Name, uidDownvoted, uidUpvoted, votes } = doc.data();
        newHeroes.push({
          key: doc.id,
          doc,
          Name,
          uidDownvoted,
          uidUpvoted,
          votes
        });
      });
      setHeroesArr(newHeroes);
    });
  };

  const onUpVote = i => {
    const collRef = db.collection("characterOptions");
    setHeroesArr(heroesArr =>
      heroesArr.map((item, o) => {
        if (i === o && !item.uidDownvoted && !item.uidUpvoted) {
          collRef.doc(item.key).update({
            votes: firebase.firestore.FieldValue.increment(1),
            uidUpvoted: true
          });
        } else if (i === o && !item.uidDownvoted && item.uidUpvoted) {
          collRef.doc(item.key).update({
            votes: firebase.firestore.FieldValue.increment(-1),
            uidUpvoted: false
          });
        } else if (i === o && item.uidDownvoted && !item.uidUpvoted) {
          collRef.doc(item.key).update({
            votes: firebase.firestore.FieldValue.increment(2),
            uidUpvoted: true,
            uidDownvoted: false
          });
        }
        return item;
      })
    );
  };

这是标记

 return (
    <div className="App">
      <button onClick={onFetch}>click</button>
      {heroesArr.map((item, i) => (
        <div key={item.key}>
          <p>{item.Name}</p>
          <p>{item.votes}</p>
          {item.uidDownvoted && <p>this has been downvoted</p>}
          {item.uidUpvoted && <p>this has been upvoted</p>}
          <button onClick={() => onUpVote(i)}>Upvote</button>
        </div>
      ))}
    </div>
  );

我显然只是希望数组更新,而不是每次触发点击事件时创建一个额外的更新副本。

【问题讨论】:

    标签: reactjs firebase google-cloud-firestore


    【解决方案1】:

    你有两个选择:

    1. 始终清除数组
    2. 执行增量更新

    由于第一个选项最简单,我将向您展示其代码。

    现在,您在 onSnapshot 之外声明您的 newHeroes,即使您只在其中使用它。这意味着每次循环 coll.forEach() 时,您都会将所有元素添加到 newHeroes,包括您之前读过的元素。

    最简单的选择是在回调中声明newHeroes,这样每次回调运行时它都会开始为空。

    db.collection("characterOptions").onSnapshot(coll => {
      const newHeroes = [];
      coll.forEach(doc => {
        const { Name, uidDownvoted, uidUpvoted, votes } = doc.data();
        newHeroes.push({
          key: doc.id,
          doc,
          Name,
          uidDownvoted,
          uidUpvoted,
          votes
        });
      });
      setHeroesArr(newHeroes);
    });
    

    另一种方法是使用 Firestore 为您提供的有关哪些文档是新文档、哪些文档已更新等信息。要获取此信息,您需要遍历 coll.documentChanges。有关这方面的示例,请参阅view changes between snapshots 上的文档。

    【讨论】:

      猜你喜欢
      • 2019-09-30
      • 2020-02-05
      • 1970-01-01
      • 1970-01-01
      • 2016-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-21
      相关资源
      最近更新 更多