Why Does Firebase Lose Reference Outside the Once() Function

Why does firebase on value not run the listener function when the reference doesn't exist, but once value does?

I needed to upgrade Firebase to the lastest version (3.0.5 -> 3.2.0)

npm install --save firebase

Not getting data from firebase on opening the app

Data is loaded from Firebase asynchronously. Since this may take some time, your main JavaScript code will continue to run, so that the user can continue to use the app while the data is loading. Then when the data is available, your callback is invoked with that data.

What this means in your code is that (for example) right now your setUserdata is called before the grabbedData.push(snapshot.val()) has run, so you're setting any empty user data. You can most easily see this by setting some breakpoints on the code and running it in a debugger, or by adding logging and checking the order of its output.

console.log("1");
await firebase
.database()
.ref(`/users/`)
.orderByKey()
.on("value", (snapshot, key) => {
console.log("2");
});
console.log("3");

When you run this code, the output will be:

1

3

2

This is probably not what you expected, but it is exactly correct and does explain your problems.


The solution for this is always the same: any code that needs the data from the database must be inside the callback, or be called from there.

So for example:

await firebase
.database()
.ref(`/users/`)
.orderByKey()
.on("value", (snapshot, key) => {
grabbedData.push(snapshot.val());
setUserdata(grabbedData);
});

this will ensure that setUserdata is called whenever you updated the grabbedData.


Since you have much more code that depends on grabbedData, that will also have to be inside the callback. So the entire if (grabbedData) { block will need to be moved, and probably others. If you keep applying the solution above, the code will start working.

This is a very common problem for developers that are new to calling asynchronous cloud APIs, so I highly recommend reading some of these other answers:

  • Why Does Firebase Lose Reference outside the once() Function?
  • Best way to retrieve Firebase data and return it, or an alternative way
  • How do I return the response from an asynchronous call? (this one is not specific to Firebase, as the problem is not specific to Firebase)

Results from realtime db not available when called

The simplest way to get some data to show is to move update the state right after you add an item to the array:

useEffect(() => {
const userArr = [];
data.map(item => {
item.members.forEach((username: string) => {
database()
.ref(`users/${username}`)
.on('value', snapshot => {
userArr.push(snapshot.val());
setUsers(userArr); // br> });
});
});
};
}, []);

Now the UI will update each time that a user is loaded from the database.

I also recommend reading some more about asynchronous loading, such as in Why Does Firebase Lose Reference outside the once() Function?



Related Topics



Leave a reply



Submit