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

Я думал о том, чтобы переключить класс в элементе списка, а затем анимировать элемент, как это (обратите внимание, я использую Angular, но эта статья применима ко всем фреймворкам):

onClickItem(): void {
   item.isActive = true;
}
animations: [
   trigger("isActive", [
      state("true", style({
         backgroundColor: "#08aeea",
         color: "#fff"
      })),
      transition("* => true", animate("150ms ease-in"))
   ])
]

Сладкий, хорошо, слишком просто. Я пробую это в своем списке, и вуаля работает как волшебство, затем я заметил что-то забавное, иногда я нажимал на элемент списка, и анимация наполовину запускалась, мигала и возвращалась в нормальное состояние - что происходит ???

Не собираюсь лгать, это озадачило меня примерно на час. Затем я посмотрел, как рендерил свой список из Firestore:

this.groups$ = this.getGroupsAsObservable(); 
// groups$ to indicate is an Observable
getGroupsAsObservable(): Observable<Group[]> {
   return this.afs.collection<Group>("groups").valueChanges();
}

Обратите внимание на часть valueChanges () - это секретный соус, который позволяет вашему приложению передавать данные из firestore в реальном времени.

Теперь происходило то, что при нажатии на элемент за кулисами он проверял, принадлежит ли этот элемент группе, и, если нет, добавлял элемент в группу, а также небольшой фрагмент данных, в котором перечислялись связанные элементы для та группа (объект) в Firestore.

Это означало, что документ группы изменился и вызовет повторную визуализацию в нашем приложении!

Здесь я понял, что мне нужно, чтобы список моих групп был чисто статическим.

На самом деле это было довольно сложно, нигде в документации не упоминаются «статические» или «однократно прочитанные» данные.

Первое, что мне нужно было для данных, - это вернуть снимок данных. В документации было немного об этом:

getUsersGroupsOnce(userId): Promise<QuerySnapshot> { 
// return a static snapshot of the users groups
   return this.afs.collection("groups", ref =>      
      ref.where(`users.${userId}`, "==", true)
   )
   .ref.get(); // this is the static part
}

Милая, теперь у меня есть статическая ссылка - мне нужно построить для этого массив, следуя документам, которые я сделал:

this.fb.getUsersGroupsOnce(user.uid).then(q => {
   q.forEach(doc => {
     console.log(doc.data())
   });
});

Хорошо, теперь у меня есть данные, которые мне просто нужно отправить в массив, верно? Я пробовал это:

q.forEach(doc => {
   this.groups.push(doc.data());
});

Но машинописный текст жаловался, поэтому я как бы заставил это сделать так:

q.forEach(doc => {
   this.groups.push(doc.data() as Group);
});

И вуаля, теперь у меня есть статический список - или, как я люблю его называть, «прочитал один раз». Теперь я знаю, что потоки данных в реальном времени 99/100 - это здорово, но полезно знать, как время от времени получать статические данные.

Есть способ лучше? Не стесняйтесь оставлять комментарии ниже.