【问题标题】:Array Of Objects from State Returning length 0 when queried, but logging the array shows the proper length [duplicate]来自状态的对象数组在查询时返回长度 0,但记录数组显示正确的长度 [重复]
【发布时间】:2020-07-23 10:40:02
【问题描述】:

在函数内部,我首先创建一个当前状态的数组,用于 for 循环。但是,当尝试获取它的长度时,它返回 0。从状态和新数组中记录数组表明该数组确实包含正确的对象,甚至将长度显示为适当的数量。

console.log(this.state.teams);
console.log(this.state.teams.length);
let sortedTeams = this.state.teams;
console.log(sortedTeams);
console.log(sortedTeams.length);

什么可能导致长度返回为 0,即使它显然不是? 数组从 firestore 映射如下:

getTeamsAndSort() {
    let teams = [];
    docRef.collection('Teams').get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            let name = doc.data().name;
            let seeding = doc.data().seeding;
            let team = {name, seeding};
            teams.push(team);
        });
        teams.sort((a, b) => (a.seeding > b.seeding) ? 1 : -1);
    });
    this.setState({teams});
};

在我调用 getTeamsandSort() 后立即调用我需要团队 [] 长度的函数,以防这是一个异步问题。

【问题讨论】:

    标签: javascript arrays reactjs google-cloud-firestore


    【解决方案1】:

    什么可能导致长度返回为 0,即使它是 显然不是??

    这是因为当您登录时,长度 0。但是,如果您将鼠标悬停在“i”图标上(在 Chrome 检查控制台中),您将看到一条消息,指出随着对象的变化,控制台中的对象也会更新。

    您可以通过以下方式防止误导性日志:

    console.log(JSON.parse(JSON.stringify(sortedTeams)));
    

    您的问题的可能解决方案:

    getTeamsAndSort = () => {
        let teams = [];
        docRef.collection('Teams').get()
        .then(querySnapshot => {
            querySnapshot.forEach(function(doc) {
                let name = doc.data().name;
                let seeding = doc.data().seeding;
                let team = {name, seeding};
                teams.push(team);
            });
            teams.sort((a, b) => (a.seeding > b.seeding) ? 1 : -1);
            return new Promise((resolve, reject) => {
                // resolve the promise after state is set
                this.setState({teams}, resolve);
            })
        });
    };
    

    然后,如果您需要在调用getTeamsAndSort 后立即使用this.state.teams,请等待Promise 以确保在记录状态或访问其属性之前更新状态。

    async someFunc() {
        await getTeamsAndSort()
        console.log(JSON.parse(JSON.stringify(sortedTeams)));
    }
    

    【讨论】:

      【解决方案2】:

      docRef.collection('Teams').get() 是异步的,在查询完成之前立即返回。事实上,所有返回 Promise 的函数的行为方式都是一样的。您的代码只能在 then 块中的 promise 解析后使用查询结果。

      在数据库结果完成之前,您的代码使用空的团队数组调用 this.setState({teams});。您应该只在回调中设置状态:

      getTeamsAndSort() {
          let teams = [];
          docRef.collection('Teams').get()
          .then(querySnapshot => {
              querySnapshot.forEach(function(doc) {
                  let name = doc.data().name;
                  let seeding = doc.data().seeding;
                  let team = {name, seeding};
                  teams.push(team);
              });
              teams.sort((a, b) => (a.seeding > b.seeding) ? 1 : -1);
              // only set the state after the teams are available
              this.setState({teams});
          });
      };
      

      还请记住,您将无法在调用 getTeamsAndSort 后立即访问团队的长度,因为整个事情现在是异步的。最重要的是,您必须学习如何有效地处理 Promise 才能处理这样的数据库查询。

      【讨论】:

      • 我在发布之前尝试过这个,但是在那个括号内,编译器会抛出一个错误,说“这是未定义的”,即使我将它绑定到那个函数。有什么想法吗?
      • 我编辑了答案以将 => 语法用于 lambda 函数,它应该保留 this
      • 谢谢你这工作变化很好,承诺绝对是我需要研究的东西。
      猜你喜欢
      • 1970-01-01
      • 2020-11-18
      • 2012-10-16
      • 1970-01-01
      • 1970-01-01
      • 2018-12-10
      • 1970-01-01
      • 2017-08-16
      • 2021-12-03
      相关资源
      最近更新 更多