Home > database >  Updating the state correctly after fetch data from firestore
Updating the state correctly after fetch data from firestore

Time:03-22

I am trying to use Firestore Snapchats to get real time changes on a database. I am using react-native-cli: 2.0.1 and react-native: 0.64.1 .

export const WelcomeScreen = observer(function WelcomeScreen() {
    const [listData, setListData] = useState([]);
    
    const onResult = (querySnapshot) => {
       const items =  []
       firestore()
       .collection("Test")
       .get()
       .then((querySnapshot) => {
           querySnapshot.forEach(function(doc) {
             const tempData = {key: doc.id, data: doc.data}
              items.push(tempData);
           });
           setListData(items)
        });
      }
      
      const one rror = (error) => {
        console.error(error);
      }
      
      firestore().collection('Test').onSnapshot(onResult, one rror);

}

Every thing is working perfectly, until I use setListData to update the data list. The App does not respond anymore and I get a warning message each time I try to add or delete data from the database

Please report: Excessive number of pending callbacks: 501. Some pending callbacks that might have leaked by never being called from native code

I am creating a deadlock by setting the state this way?

CodePudding user response:

First, you don't want to set up a snapshot listener in the body of your component. This results in a growing number of listeners, because every time you render you add a new listener, but every listener results in rendering again, etc. So set up the listener just once in a useEffect:

const [listData, setListData] = useState([]);

useEffect(() => {
  function onResult(querySnapshot) {
    // ...
  }
  function one rror(error) {
    console.log(error);
  }

  const unsubscribe = firestore().collection('Test').onSnapshot(onResult, one rror);
  return unsubscribe;
}, []);

In addition, your onResult function is going to get called when you get the result, and yet you're having it turn around and immediately doing a get to re-request the data it already has. Instead, just use the snapshot you're given:

function onResult(querySnapshot) {
  const items = []
  querySnapshot.forEach(function(doc) {
    const tempData = {key: doc.id, data: doc.data()}
    items.push(tempData);
  });
  setListData(items);
}

CodePudding user response:

Dharmik, it is okay to use useState outside of functional components, if said component is a custom hook, this doesn't look like it and I would probably make it a hook, or return the answers to call it in a functional component with a setter.

  • Related