How to get all Firebase active listeners

Today I tried to get all active listeners I had in Firebase (client side). After doing some research, it seems that there is no API that returns the number of listeners active in a client.

You need to keep a counter.

So... Let's do it.

Example using React

Let's assume that we have 2 Firebase database listeners:

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

const Test = () => {
    
    const [total, setTotal] = useState(0);
    
    useEffect(() => {
        
        let listener_1 = firebase.database().ref(`/posts`).on('value', snapshot => {
            
            let posts = snapshot.val();
            
        });
        
        let listener_2 = firebase.database().ref(`/visits`).on('value', snapshot => {
            
            let visits = snapshot.val();
            
        });
        
        setTotal(total + 2);
        
    }, []);
    
    return(
        
        <div>
            There are {total} active listeners.
        </div>
        
    );
    
}

export default Test;

total is counting the number of active listeners.

Problem

Let's assume that we want to display the visists and posts instead of the active listeners. We would do:

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

const Test = () => {
    
    const [posts, setPosts]   = useState(0);
    const [visits, setVisits] = useState(0); 
    const [total, setTotal]   = useState(0);
    
    useEffect(() => {
        
        let listener_1 = firebase.database().ref(`/posts`).on('value', snapshot => {
            
            let posts = snapshot.val();
            
            setPosts(posts);
            
        });
        
        let listener_2 = firebase.database().ref(`/visits`).on('value', snapshot => {
            
            let visits = snapshot.val();
            
            setVisits(visits);
            
        });
        
        setTotal(total + 2);
        
    }, []);
    
    return(
        
        <div>
            Total visits: {visits}
            Total posts: {posts}
        </div>
        
    );
    
}

export default Test;

Everything seems to work fine, but if we go to a new URL, listener_1 and listener_2 will be still active. This will cause a leak of memory error, when both try to set a new state.

Solution

The solution is to clean up both listeners before unmounting the component.

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

const Test = () => {
    
    const [posts, setPosts]   = useState(0);
    const [visits, setVisits] = useState(0); 
    const [total, setTotal]   = useState(0);
    
    useEffect(() => {
        
        let listener_1 = firebase.database().ref(`/posts`).on('value', snapshot => {
            
            let posts = snapshot.val();
            
        });
        
        let listener_2 = firebase.database().ref(`/visits`).on('value', snapshot => {
            
            let visits = snapshot.val();
            
        });
        
        setTotal(total + 2);
        
        // This lines of code will execute just before unmounting the component
        // Clean up = deactivate functions that could change the state of the component
        return () => {
            
            firebase.database().ref(`/posts`).off('value', listener_1);
            firebase.database().ref(`/visits`).off('value', listener_2);
            
            // At this point there are 0 active listeners
            
        }
        
    }, []);
    
    return(
        
        <div>
            Total visits: {visits}
            Total posts: {posts}
        </div>
        
    );
    
}

export default Test;

Cleaning up means to deactive functions that could change the state of a component when we are not using it anymore. If we clean up the listeners we guarantee that we don't keep listeners active when we change to a new component.

Anyway, in the worst case scenario, even if we kept active listeners, it won't be a big deal as Frank van Puffelen states. The critical thing is the amount of data to be read.

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