只有第一个元素显示状态更新,直到发生外部事件

Only first element is showing state updates until external event

与我的

相关并且几乎是直接扩展

我正在使用 useEffect 运行 一个从 firebase 获取数据的函数。 已抓取数据,但只有第一个元素显示添加到状态的附加信息。

const [expenses, setExpenses] = useState([]);
const roster = [];
var db = firebase.firestore();

React.useEffect(() => {
    const getRoster = async () => {
      db.collection("Roster")
        .get()
        .then((querySnapshot) => {
          querySnapshot.forEach((doc) => {
            // doc.data() is never undefined for query doc snapshots
            var data = doc.data();
            data.ID = doc.id;

            roster.push(data);
          });

          // setExpenses(roster);
          // console.log("expenses", expenses);
          // console.log("roster", roster);
        })



这是按预期工作的,注释掉的代码是我上一个问题的解决方案。 我添加了下面的代码并遇到了我的新问题。

        .then(() => {
          roster.forEach((member) => {
            let total = 0;
            db.collection("Attendance Entries")
              .where("attendees", "array-contains", member.ID)
              .get()
              .then((querySnapshot) => {
                querySnapshot.forEach((doc) => {
                  // doc.data() is never undefined for query doc snapshots
                  total++;
                  member.total = total;
                });
                setExpenses(roster);
              });
          });
        });
    };

    getRoster();
  }, []);


第一个元素在初始加载时显示“member.total”,其他元素仅在状态更改后出现。不知道为什么会这样..

感谢您的帮助!

Example of what I am seeing on initial load

我没有完全遵循你的所有代码,但我发现你在你说你有问题的代码部分的 forEach 循环中排队状态更新的方式可能存在问题.当您在循环中排队状态更新时,您 必须 使用功能状态更新,以便每个排队的更新不会吹走(覆盖)以前的状态.

您可以迭代之前计算的 roster 数组,然后计算每个 member 的文档总数并改变成员对象,然后使用功能状态更新来附加新成员反对支出状态数组。

.then(() => {
  roster.forEach((member, index) => {
    let total = 0;
    db.collection("Attendance Entries")
      .where("attendees", "array-contains", member.ID)
      .get()
      .then((querySnapshot) => {
        querySnapshot.forEach((doc) => {
          // doc.data() is never undefined for query doc snapshots
          total++;
        });
        member.total = total;
        setExpenses(expenses => expenses.concat(member));
      });
  });
});