Listeners don't cache results on Firebase

I wonder how much time do I lose on dumb mistakes.

A few days ago, some users reported an error of a sidebar's message panel on one of my websites. It wasn't updating after publishing a new comment. Thus, users thought their messages were lost.

After some testing, I couldn't find any explanation, the component was a simple Firebase listener getting the last comments from the database:

jsx
import { useState, useEffect } from 'react';
import firebase                from './Firebase';

const GetLastComments = (numberOfComments) => {
    
    const [comments, setComments] = useState([]);
   
    useEffect( () => {
        
        let ref = firebase.database().ref('replies');
      
        let listener = ref.limitToLast(numberOfComments).on('value', snapshot => { 
            
            let replies = snapshot.val();
           
            if(replies){
                
                let sortedReplies = Object.entries(replies).reverse();
                
                setComments(sortedReplies);
                
            } 
            
        });
        
        return () => ref.off('value', listener);
     
    }, [numberOfComments]);
    
    return comments;
  
}

export default GetLastComments;

The problem

The component wasn't getting updated data, messages were incoherent, so it seemed like a Firebase cache problem. I published a question on StackOverflow, I wanted to know if Firebase cached results and the answer was negative.

The solution

After going back and forward for a few days, I discovered that the delay in getting the last comments was a mistake of mine. Before limitToLast() I had to order the reference; I needed to use the orderByKey() function.

So, this was the final result:

jsx
import { useState, useEffect } from 'react';
import firebase                from './Firebase';

const GetLastComments = (numberOfComments) => {
    
    const [comments, setComments] = useState([]);
   
    useEffect( () => {
        
        let ref = firebase.database().ref('replies');
      
        let listener = ref.orderByKey().limitToLast(numberOfComments).on('value', snapshot => { 
            
            let replies = snapshot.val();
           
            if(replies){
                
                let sortedReplies = Object.entries(replies).reverse();
                
                setComments(sortedReplies);
                
            } 
            
        });
        
        return () => ref.off('value', listener);
     
    }, [numberOfComments]);
    
    return comments;
  
}

export default GetLastComments;

Conclusions

It doesn't matter if you push or update a branch, firebase.databse().ref().on() listener always returns updated results. In case you are getting incoherent data or some delays in the results, check if you have ordered the Firebase reference somehow (orderByKey(), orderByValue() or orderByChild()).

Hi, I'm Erik, an engineer from Barcelona. If you like the post or have any comments, say hi.