Convert A Firebase Database Snapshot/Collection To An Array In Javascript

Because Firebase is a NoSQL JSON data store, you might have noticed that when you get some data from Firebase that it is an object. If the title wasn’t obvious enough, we are talking about using Firebase Realtime Database in a web application.

Take the following example:

firebase.database().ref('/posts').on('value', function(snapshot) {
    console.log(snapshot.val());
});

Let’s imagine that we have 20 posts in our database. You’ll get back an object containing keys and objects for all of our imaginary posts.

If you’re working with a Javascript framework or library such as Aurelia, then you’ll know that iterating an object opposed to an array is more complicated (especially HTML templating).

So, here is a function I ended up writing which I use quite a lot in my Firebase applications:

function snapshotToArray(snapshot) {
    var returnArr = [];

    snapshot.forEach(function(childSnapshot) {
        var item = childSnapshot.val();
        item.key = childSnapshot.key;

        returnArr.push(item);
    });

    return returnArr;
};

I am a big fan of verbose functions, although using the power of modern spec Javascript you can create a more condensed shorthand equivalent of the above function.

To use our newly created function

firebase.database().ref('/posts').on('value', function(snapshot) {
    console.log(snapshotToArray(snapshot));
});

If you are using a transpiler like Babel, writing using TypeScript or targeting evergreen browsers like Chrome and Firefox, a nicer solution is:

const snapshotToArray = snapshot => Object.entries(snapshot).map(e => Object.assign(e[1], { key: e[0] }));

You call our shorthand function the same, but it’s a less verbose and harder to understand one-line function. Special thank you to the commenters below who have proposed their own solutions as well.

18 responses to “Convert A Firebase Database Snapshot/Collection To An Array In Javascript”

  1. allen joslin says:

    An ES7 one-liner:

    let arr = Object.entries(snapshot).map(e => Object.assign(e[1], { key: e[0] }));

  2. Dwayne says:

    Allen,

    That is really nice. Thanks for sharing that!

  3. Valery says:

    Thanks, very useful pattern !

  4. Gabriel says:

    Very Thanks.

  5. Moshiour Rahman says:

    That key interrupts the loop number, for example if a node only contain 2 child then another extra child ‘key’ is added. that increase the loop number.

  6. haytham says:

    did you try it ?

    the problem in the first place is we get object of values…
    so we dont have .forEach … because its unknown object and not array !

  7. Bobr says:

    ES6:
    Object.keys(s.val() || {}) .map(k => s.val()[k]);

  8. Kevin Cho says:

    Thank you for sharing snapshotToArray(snapshot) 🙂

  9. Chris says:

    Great help, thanks

  10. DKMin says:

    Wow, thanks a lot. Dwayne & allen joslin

  11. Hey, thanks for sharing

    what do you think about this approach?
    https://gist.github.com/fipo/483a07bc741e7f4b470b8bc3e6c7bdac

    I prefer to keep the id and use it for the `key=` prop

  12. John francis says:

    I am using similar solution in angular with ionic 3. My issue is this: when I bind my datas to html, I could not get a unique key for each entry.

    I am trying to implement a like/unlike button right on esch entry binded but the key for each entry is my problem.

    For example: adding a delete button on each binded entry. When clicked, it deletes another entry and not the actual post.

    Using navParams works fine but one has to goto post details first.

    How do I get a unique key for each post binded without going to post details first? Any ideas please?

    Posts are binded in timeline.html and logins in timeline.ts and post details are binded in post-details.html and navparams from post-details.ts

  13. Carlos Guillen says:

    Object.values(snapshot.val()) also does the job

  14. Valmir Verbani says:

    I can’t stress how helpful this was. I am finding the documentation on Firebase isn’t the most clear. Thank you for posting this solution!

  15. yukti says:

    hello please tell me how to fetch the resent updated value from firebase and display in map as a marker

  16. SeriousGUy888tydhsbf says:

    Thank you for sharing this!

  17. GM says:

    I still have no idea why they not returning an array response instead…

  18. Nicola says:

    Thank you!

Leave a Reply

Your email address will not be published. Required fields are marked *