React-native-firebase: [v6][database] snapshot values not in the correct order

Created on 6 Aug 2019  路  13Comments  路  Source: invertase/react-native-firebase

Issue



I have started to use RN version 0.60.4 , I was using 0.57.5 before. I use firebase real time database. I was fetching last 50 data, now I see that it brings me last 50 but in random order.. I dont understand the reason of it. I had no problem in installlation, all works fine but just fetching data brings random last 50..

Platform: Android

I have checked if its from Flatlist or something but its not from those.. In old version its working fine, but now in latest RN version it works wrong.

package.json

"dependencies": {
    "@react-native-community/async-storage": "^1.6.1",
    "@react-native-firebase/app": "^0.1.2",
    "@react-native-firebase/database": "^0.1.2",
    "axios": "^0.19.0",
    "immutable": "^4.0.0-rc.12",
    "react": "16.8.6",
    "react-native": "0.60.4",
    "react-native-device-info": "^2.3.2",
    "react-native-gesture-handler": "^1.3.0",
    "react-native-iap": "^3.3.7",
    "react-native-image-picker": "^1.0.2",
    "react-native-indicators": "^0.13.0",
    "react-native-onesignal": "^3.3.1",
    "react-native-progress": "^3.6.0",
    "react-native-router-flux": "^4.0.6",
    "react-native-sound": "^0.11.0",
    "react-navigation": "^3.11.1",
    "react-redux": "^7.1.0",
    "redux": "^4.0.4",
    "redux-logger": "^3.0.6"
  },

My Code:

import { firebase } from '@react-native-firebase/database';

// CODE //
 firebase.database().ref('Chat/'+LL).limitToLast(50).on('value', function (snapshot) {
            let array = [];
            let data = snapshot.val()

            Object.keys(data).map(function(key, index) {
                console.log(data[key])
                array.push(data[key])
            });
            this.setState({ chats: array, loaded: true });
        }.bind(this));
Database >= 6

Most helpful comment

Hey @losheredos,

Can you try with snapshot.forEach() -> this guarantees the order, whereas snapshot.val() keys won't - see the docs here for forEach()

So your code above becomes:

firebase
  .database()
  .ref('Chat/' + LL)
  .limitToLast(50)
  .on('value', snapshot => {
    let array = [];
    snapshot.forEach(function(childSnapshot) {
      // const key = childSnapshot.key;
      const childData = childSnapshot.val();
      console.log(childData);
      array.push(childData);
    });
    this.setState({ chats: array, loaded: true });
  });

All 13 comments

Hey @losheredos,

Can you try with snapshot.forEach() -> this guarantees the order, whereas snapshot.val() keys won't - see the docs here for forEach()

So your code above becomes:

firebase
  .database()
  .ref('Chat/' + LL)
  .limitToLast(50)
  .on('value', snapshot => {
    let array = [];
    snapshot.forEach(function(childSnapshot) {
      // const key = childSnapshot.key;
      const childData = childSnapshot.val();
      console.log(childData);
      array.push(childData);
    });
    this.setState({ chats: array, loaded: true });
  });

Hey @Salakar ,
I actually tried it just forgot to mention it. When I try your suggestion which I also tried before, I get error:

this._ref.child is not a function.

Additionally I tried as just a different way of it before as well but didnt help:
let data = Object.values(snapshot.val());

Hey, could you send over a sample data set and I'll get this sorted tomorrow.

Fetching:
resim

Flatlist:
resim

Write:
resim

RenderItem:
resim

Hope it will make you understand better and will be enough

Thanks, will get this looked at

Which platform is this as well, Android or iOS? Thanks

Sorry that didnt mention it, its Android

@losheredos what does the data in the database look like? Do you have a list of generated keys with text or is it more complex? I ran a basic test and it works my end, so assume it's the data being in a different format.

Console.log(snapshot.val())
resim

Some of them
resim

Object.values(snapshot.val());
resim

Ok makes more sense, can you give me an example of what one of them objects looks like? Replace any sensitive data with something else of course :D

I have edited. Look the case is in my current app which is online now, chat works fine with as in correct order. But now in when I work with RN 0.60.4, they are messed up and mixed. The main difference is I cant forEach snapshot directly without getting val() of it.

So maybe this mapping with Object.values or Object.keys mixes it I'm not sure but when I try in old way(directly forEach to snapshot) as I mention in top comments I get this error:

this._ref.child is not a function.

Hope I'm not doing something silly and taking your time for nothing.. :)

Edit: OK I think this Object.values and Object.keys mixes things up, because I when I consolling it without converting them to array, I see that they are in true order. Because when we map object like this, it gets every element by its key and keys are not ordered properly because of alphabetical order..

Edit2: I think I found workaround for this issue. But still question mark for why we cant forEach snapshot as before?

resim

Ok sorted it - even has a comment on the code with the issue... woops!

So anyway to answer your questions:

  • When doing Object.keys or Object.values, you're iterating over the data we get back from the native calls. When this comes to JavaScript, the order can be anything - hence why it wont work.

  • When doing forEach (which is now fixed), we iterate over an array of the keys which is sent from native which is in the correct order, and grab the data from the object it relates to.

Will get a version pushed up soon (couple of other things to sort too). Thanks for your help.

This has now been published in 0.1.3 of the new packages, see https://github.com/invertase/react-native-firebase/issues/2025#issuecomment-519166641.

Thanks

Was this page helpful?
0 / 5 - 0 ratings