Issue retrieving Firebase data on React Native app - javascript

I'm trying to display the WeightGoal that's already been stored on my Firebase RealTime Database, but I'm getting the following error. "Objects are not valid as a React child (found: object with keys {…})"
Here's my json file:
Here's my componentWillMount code:
componentWillMount() {
const { currentUser } = firebase.auth();
firebase
.database()
.ref(`/users/${currentUser.uid}/goals`)
.on('value', snap => {
this.setState({ WeightGoal: snap.val()})
})
}
And here's how I'm referencing the value inside of render:
{this.state.WeightGoal}
My expectation is to see 170 displayed on the screen.
Any help would be greatly appreciated.

snap.val() is the object consisting of the goal object in your database, because that is what you are referencing:
.ref(`/users/${currentUser.uid}/goals`)
So, if you want to store only the WeightGoal property, the line, where you use this.setState should look like this:
this.setState({ WeightGoal: snap.val().WeightGoal })
P.S. Next time try adding console.log(this.state) into render() to see what you are displaying. Or add a breakpoint in Chrome Debugger, which is a more reliable way.

Related

React FIrebase Failed-precondition

Im using Firebase to store some data in my React app. Its working fine on my local emulator with the same settings, but when i publish the app, i get this error:
#firebase/firestore: Firestore (9.12.1): Uncaught Error in snapshot listener: {"code":"failed-precondition","name":"FirebaseError"}
Im using the where() clause, and i red i need to add some sort of index in my firebase rules.
useEffect(() => {
if (activeList === 'null') {
} else {
const userRef = collection(database, activeList.id);
const sort = query(userRef, where("checked", "==", showDoneTodos), orderBy('title', 'asc'))
const unsubsctibeAllTodos = onSnapshot(sort, (snapshot) => {
setAllTodos(snapshot.docs.map(doc => ({
id: doc.data().id,
title: doc.data().title,
desc: doc.data().desc,
checked: doc.data().checked
})
))
})
return () => {
unsubsctibeAllTodos()
}
}
}, [activeList, showDoneTodos])
Some info:
activeList is an object with and ID. The problem is that this is generated live so i cant preconfigure any collection ID before i publish.
showDoneTodos is a boolean.
Any guidance would be very welcome!
Thanks!
Firebase logs this error when the required index is missing. It only shows this error when you use the onSnapshot method. When you use the getDocs methode it will show the good old link to create the index in the Firebase console. A solution is to create a similar request with the getDoc methode, create the index and switch back to the onSnapshot methode.
It seems that Firebase does not provide a link to create the necessary index anymore. They only provide the error code:{"code":"failed-precondition","name":"FirebaseError"}
The solution is the same, go to Firebase -> Indexes and add it there...

How to enable persistence on reactfire?

I'd like to implement Firestore offline persistence on my PWA React app using the reactfire library.
const firestore = useFirestore().enablePersistence();
let documentReference = firestore
.collection("food")
.doc("milkshake");
const { data } = useFirestoreDocData(documentReference);
but running the code i get an error:
FirebaseError: Firestore has already been started and persistence can no longer be enabled. You can only enable persistence before calling any other methods on a Firestore object.
This component is wrapped inside a <Suspense> as mentioned in the documentation
That database read is the only one that i make in the entire app, how can i solve?
Edit.
Using the example that #Ajordat gave, I've imported the preloadFirestore function inside the App component I do get an error:
"Cannot read property 'name' of undefined".
Whereas adapting (because I cannot use hooks inside the fetch function)
the example from #DougStevenson: I've imported useFirestore function in the App component (in order to get the Firestore object) to enable persistence, and then importing it (useFirestore) into my component in order to retrieve the data, but now, I get the same error as before,
Firestore has already been started and persistence can no longer be enabled.
Edit 2:
I've tried to enablePersistence without errors, thank guys, this is my approach, let me know if it is the best:
const firestore = useFirestore();
React.useEffect(() => {
firestore.enablePersistence();
}, []);
And in my custom component:
let docRef = useFirestore()
.collection("food")
.doc("milkshake");
let document = useFirestoreDocDataOnce(docRef);
console.log(document)
But now I do have a problem, when I log the document, the data are not emitted instantly, yeah I know that it is an asynchronous operation, but the component is wrapped inside a <Suspense>, in this way:
<Suspense fallback={<div>Loading</div>}>
<FoodComponent foodName={"Milkshake"} />
</Suspense>
But I don't see the loading text before the component is actually rendered.
Does the suspense fragment show the fallback component only while is loading the function (useFirestore) and not the actual data?
Well, I've solved, have to destructure the data, doing like that:
let docRef = useFirestore()
.collection("food")
.doc("milkshake");
let { data: document } = useFirestoreDocData(docRef);
console.log(document)
On other JavaScript libraries for Firestore, enablePersistence() returns a promise. That means it will complete some time in the future, with no guarantees how long it will take. If you're executing the query immediately after you call enablePersistence(), without waiting for the returned promise to become fulfilled, then you will see this error message. That's because the query "beats" the persistence layer and effectively executes first.
You will have to figure out how to use that promise to wait until it's OK to make that query with persistence enabled. For example:
seFirestore().enablePersistence()
.then(() => {
let documentReference = firestore
.collection("food")
.doc("milkshake");
const { data } = useFirestoreDocData(documentReference);
})
.catch(error => {
console.error("enablePersistence failed", error);
})
Notice how the query will complete only after the persistence is fully enabled.
Thanks for the suggestion guys #DougStevenson and #Ajordat
In app component:
import { useFirestore } from "reactfire"
...
const firestore = useFirestore();
React.useEffect(() => {
firestore.enablePersistence();
}, []);
In your custom component, where you want to use Firestore:
import { useFirestore, useFirestoreDocData /* or what you want to use */ } from "reactfire"
let docRef = useFirestore()
.collection("food")
.doc("milkshake");
let { data: document } = useFirestoreDocData(docRef);
console.log(document);

Manipulating documents in Firebase collection with Vuex [Vuex/Vuexfire]

I've a simple question but I can't find the answer.
I'm using Vuexfire to import data from Firebase in Vuex.
const state = {
ricettario: [] // data that contains all recipes (objects)
}
const actions = {
// Get data from Firebase
init: firestoreAction(({ bindFirestoreRef }) => {
bindFirestoreRef('ricettario', db.collection('ricettarioFirebase'))
}),
}
It works perfectly but I want to manipulate every document of the collection 'ricettarioFirebase'. With vue + firebase was easy, with .get() and .then()
I can't find a solution! I thought using GETTERS is the best way to do that but I'm new with Vuex and Vuexfire so I don't know how to do that.
In particular, I want to convert this (classic firebase command):
db.collection("ricettarioFirebase")
.orderBy("data")
.get()
.then(snapshot => {
snapshot.forEach(doc => {
let ricetta = doc.data();
ricetta.data = dayjs(ricetta.data)
.locale("it")
.format("D MMMM YYYY");
ricetta.diffClass = ricetta.diff.split(" ").join("_");
this.ricettario.push(ricetta);
});
});
In Vuexfire. So change every object in the "ricettario[ ]" will be "ricetta", and I want to edit the "ricetta.diffClass" and "ricetta.data"
As you will see in the Vuexfire documentation:
Vuexfire does not handle writing data back to Firebase because you can
directly use the Firebase JS SDK to precisely update whatever you
need.
The doc gives some example of use of the "standard" JS SDK, exactly like you did in your question ("classic firebase command"). So you'll have to go this way, wrapping the database writes in Vuex Actions.

Trying to understand react native with getting local storay with AsyncStorage

I'm not able to console log the saved storage value in a component.
Here's the basic react native page:
import React from 'react';
import { AsyncStorage, StyleSheet, Text, View } from 'react-native';
const SavedExercise = (props) => {
const getStoredExercises = async () => {
const saved = await AsyncStorage.getItem('#storage_Key');
return saved;
// try {
// const saved = await AsyncStorage.getItem('#storage_Key');
// return saved;
// } catch (e) {
// // saving error
// }
};
return (
<View>
<Text>hello</Text>
{saved}
</View>
);
};
const style = StyleSheet.create({
});
export default SavedExercise;
I tried a number of various things to try to console log (or output) the saved #storage_key value. This is supposed to an object but saved in a string, and ultimately will have to JSON.parse it. but I'm just trying to get it to log. Unfortunately with no luck.
I keep getting erros like:
Objects are not valid as a React child (found: object with keys {_40, _65, _55, _72}). If you meant to render a collection of children, use an array instead.
or
Warning: Functions are not valid as a React child. This may happen if you return a Component instead of <Component /> from render. Or maybe you meant to call this function rather than return it.%s,
How do I properly get the object thats stored in #storage_key?
First of all , import { AsyncStorage } from 'react-native'; has been deprecated , you can check in the docs rn-deprecated-asyncstorage.
So now you should install rn-async storage .
After that in your code, where are you setting the async storage value like AsyncStorage.setItem('#storage_Key', 'stored value') and just an quick note yoou can only keep string values in async storage, if you want to keep array or something else you need to JSON.stringify it first and when extracting via const value = await AsyncStorage.getItem('#storage_Key') you need to again JSON.parse the value to convert into array or whatever format you want it in.
Try with this. I believe the error is due to you are using deprecated asyncstorage. Try with the one for which ive provided the link.r
Hope it helps. feel free for doubts.

How do i pass a function with props.history(path, state) in react router v4

i am facing problem on my react project, what I am doing, I pushing the route through props.history which contain two params (path, State), on state passing object which contain some keys and function. when i add a function in state object it's give me error. can somebody help me to get out of this issue.
Here is my code.
const { history } = this.props;
const data= {
index: this.props.index,
detail: this.props.object,
handleSubmit: () => { console.log("i am not passing :(");}
}
history.push('/update-task/${index}', data);
here is screenshot of error:
NOTE: when i just pass simple object and string value then it's working fine and i get the value like props.location.state.key
above code was working on react-router v3 but in react-router-dom not working.

Categories

Resources