Diego
Diego

Reputation: 681

Firebase onSnapshot realtime with react and redux - Dispatching too many actions concern

I have this react-app which displays a table with a lot of data.

And i need to know when a row of the table gets removed from firebase, but i need to do that realtime and save that data in a reducer dispatching an action so i can access that data in the rest of the app.

And I did it with an useEffect

    useEffect(() => {
        const unsubscribe = onSnapshot(
            config(terminal!),
            (snapshot) => {
                // let addedData: any[] = [];
                let deletedData: any[] = [];

                snapshot.docChanges().forEach((change) => {
                    if (change.type === 'removed') {
                        deletedData = [...deletedData, change.doc.data()];
                    }
                });

                if (deletedData.length > 0) {
                    dispatch(realtimePickups(deletedData, 'removed'));
                }
            },
            (error) => {
                console.log(error);
            },
        );

        return () => unsubscribe();
    }, []);

So, everytime something gets removed, i would dispatch an action, my problem is, is this a good way of doing this ?¿ Would i have performance problems ?¿ Would there be a problem if i dispatch like 50 actions if for some reason 50 rows get removed ?¿

If this is not the best way to do it, would you help me to improve my code.

Upvotes: 0

Views: 392

Answers (1)

Jackson
Jackson

Reputation: 1370

This line:

dispatch(realtimePickups(deletedData, 'removed'));

Can cause too many renders depending on the volume of firebase subscription calls. This also depends on two more factors:

  1. Is the deleted data used in a component and is mounted in DOM?
  2. Are you using an immutable data store?

I recommend a different variation:

  1. Install use-debounce. It has a useDebouncedCallback hook which we'll need to use.

  2. Then:

import { useDebouncedCallback } from 'use-debounce';

let deletedData: any[] = [];

const MyComponent = () => {
  // Debounce massive updates by 1second
  const deletedDataDispatch = useDebouncedCallback((data) => {  
    dispatch(data)
    deletedData = []
  }, 1000);

  useEffect(() => {
    const unsubscribe = onSnapshot(
      config(terminal!),
      (snapshot) => {
        snapshot.docChanges().forEach((change) => {
          if (change.type === 'removed') {
            deletedData = [...deletedData, change.doc.data()];
          }
        });

        if (deletedData.length > 0) {
          deletedDataDispatch(realtimePickups(deletedData, 'removed'));
        }
      },
      (error) => {
        console.log(error);
      })

    return () => unsubscribe();
  }, [])
}

Upvotes: 1

Related Questions