从 firebase 加载数组后的 setState

setState after loading an array from firebase

我在网上看到了类似的问题,但 none 他们的解决方案对我有用。

我正在用 React Native 构建一个应用程序,它从 firebase 加载信息然后显示它。我想从 firebase 加载对象,将它们放在一个数组中,然后设置状态,以便 class 在加载后重新呈现并显示它。

信息加载正常,但我找不到在数组加载后调用 setState 的方法。我尝试了 promises 并尝试使用另一个函数作为回调,但对我来说还没有任何效果。它总是在加载数组之前执行 setState。我不知道以某种方式使用 setTimeout 是否是一个好的解决方案。

这是一些代码(我想更新 this.state 中的 jArray,然后重新呈现页面):

constructor(props){
  super(props);
  this.state = {
    jArray: []
  }
}

componentDidMount(){         
   this.getJ(); 
}

async getJ(){

  let jArray = [];
  let ref = database.ref('users/' + fb.auth().currentUser.uid + '/usersJ');
  let snapshot = await ref.once('value');

  let itemProcessed = 0;
  let hhh = await snapshot.forEach(ch => {
     database.ref('J/' + ch.val()).once('value')
      .then(function(snapshot1){
        jArray.push(snapshot1);
        itemProcessed++;
        console.log(itemProcessed);
        if(snapshot.numChildren()===jArray.length){
          JadArray = jArray
        }
      })
  });

}

谢谢(:

也许你可以这样做:

  // don't forget to use an arrow function to bind `this` to the component
  getJ = async () => {
    try {
      const ref = database.ref('users/' + fb.auth().currentUser.uid + '/usersJ');
      const snapshot = await ref.once('value');

      // it might be easier just to start by getting the data into an object you can use like this
      const dataObj = snapshot.val();

      // extract the keys
      const childKeys = Object.keys(dataObj);

      // use the keys to create a function that makes an array of all the promises we want
      const createPromises = () =>
        childKeys.map(childKey => database.ref('J/' + childKey).once('value'));

      // await ALL the promises before moving on
      const jArray = await Promise.all(createPromises());

      // now you can set state
      this.setState({ jArray });

      // remember to catch any errors
    } catch (err) {
      console.warn(err);
      // you might want to do something else to handle this error...
    }
  };
}

所以最后我找到了解决问题的方法,来自:

我的代码如下所示:

async getJ(){

  let jArray = [];
  let ref = database.ref('users/' + fb.auth().currentUser.uid + '/usersJ');
  let snapshot = await ref.once('value');

  let itemProcessed = 0;
  let that = this;
  let hhh = await snapshot.forEach(ch => {
     database.ref('J/' + ch.val()).once('value')
      .then(function(snapshot1){
        jArray.push(snapshot1);
        itemProcessed++;
        console.log(itemProcessed);
        if(snapshot.numChildren()===jArray.length){
          JadArray = jArray
          that.setState({
            jadArray : jArray,
            dataLoaded : true
          },() => console.log(that.state))
        }
      })
  });
}

'this' 和 'that' 有点棘手,但现在一切正常。