I am developing an app with React Native using Firebase Realtime Database as the backend.
On an "Edit" screen, I have a form that updates the data (at a specific ID) when the submit button is pressed. Immediately after the save, it navigates to the "Details" screen of that item (react-navigation).
The Details screen pulls the data from Firebase and displays the details of the item that was just edited.
The problem is that it saves, but goes to the details screen too soon (despite navigate being in the then statement). So when it goes to details it has the old info unless I back all the way out and view the Details screen again. Below is the function called onSubmit:
const saveExisting = (data) => {
Firebase.database()
.ref("users/" + user.uid + "/items/" + itemId)
.set(data, function (error) {
if (error) console.log("Error saving existing item");
else console.log("Item Updated");
})
.then(navigation.navigate("Details", { id: itemId }));
};
The Details screen then pulls the data from Firebase as seen below. Note: I was pulling more than just the title, but simplified for this post. When testing with just title I experience the same issue (shows title prior to update).
const [title, setTitle] = useState("");
useEffect(() => {
Firebase.database()
.ref("users/" + user.uid + "/items/" + id)
.get()
.then((snapshot) => {
if (snapshot.exists()) {
snapshot.val().name && setTitle(snapshot.val().name);
} else {
console.log("No data found");
}
})
.catch((error) => {
console.log("error: " + error);
});
}, []);
I'm not sure why the update on the server hasn't gone through yet, but in general I'd recommend using onSnapshot
over get.
When you use get()
you're explicitly telling the SDK to check for the value on the server, which in this case seems to be where the problem comes for due to the (admittedly unclear) race condition.
By using onSnapshot
you'll:
set
call returns (even before the promise resolves and calls then
).