Firestore onSnapshot обновляет и добавляет массив в DOM, а не только обновляет - PullRequest
0 голосов
/ 27 мая 2019

У меня есть данные из Firestore, которые я сопоставляю с DOM, а затем обновляю на стороне клиента.Пока данные обновляются так, как я хочу, каждый раз, когда происходит событие, в DOM добавляется еще один обновленный массив.

Я думаю, что проблема в том, как настраиваются события click, но я не уверен, как еще я могу применить свои действия на стороне клиента в отношении массива.

вот моя установка и событие клика

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>
  );

Я, очевидно, просто ожидаю обновления массива, а не создания дополнительной обновленной копии каждый раз, когда щелчоксобытие запущено.

1 Ответ

0 голосов
/ 27 мая 2019

У вас есть два варианта:

  1. Всегда очищать массив
  2. Выполнять инкрементные обновления

Поскольку первый вариант самый простой, я покажу вам код для этого.

Прямо сейчас вы объявляете свой newHeroes за пределами onSnapshot, даже если вы используете его только внутри него. Это означает, что каждый раз, когда вы перебираете 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. Пример этого см. В документации по Просмотр изменений между снимками .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...