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
Reactjs - Does Render Get Called Any Time "Setstate" Is Called
Parseint VS Unary Plus, When to Use Which
Explanation of <Script Type = "Text/Template"> ... </Script>
What Is the Meaning of the "At" (@) Prefix on Npm Packages
How to Check File Input Size with Jquery
React/Jsx Dynamic Component Name
How to Get Unique Values in an Array
Iframe Src Change Event Detection
Advantages of Createelement Over Innerhtml
Seedable JavaScript Random Number Generator
Maximum Size of an Array in JavaScript
Preserving a Reference to "This" in JavaScript Prototype Functions
Async/Await Always Returns Promise
Selecting Null: What Is the Reason Behind Selectall(Null) in D3
Required Field Validations Not Working in Jquery Popup MVC 4
Are There Constants in JavaScript
Detecting Arrow Key Presses in JavaScript
Assigning Prototype Methods *Inside* the Constructor Function - Why Not