I am trying to figure out how to use react useEffect to get data from firestore.
This is my current attempt.
import React, { useHook, useEffect, useState } from 'react';
import {
useParams
} from 'react-router-dom';
import Firebase from "../../../firebase";
const ReadBlogPost = async () => {
const [loading, setLoading] = useState(true);
const [currentPost, setCurrentPost] = useState([]);
let { slug } = useParams();
useEffect(() => {
Firebase
.firestore
.collection("blog")
.doc(slug)
.get()
.then(function(doc) {
if (doc.exists) {
// setCurrentPost(doc.data());
console.log("Document data:", doc.data());
} else {
// doc.data() will be undefined in this case
console.log("No such document!");
}
})
.catch(function(error) {
console.log("Error getting document:", error);
}), []
})
return (
<div>
{currentPost.title}
</div>
)
};
export default ReadBlogPost;
The empty array at the end is an attempt to try and make sure react doesn't use up all the firestore read allowances that have been detailed in this post and this issue.
When I try this, I get an error that says:
Line 19:11: Expected an assignment or function call and instead saw an expression no-unused-expressio
The file is jsx. I have seen this post and this which means I have to transform the if statement into a ternary condition.
My attempt at changing this to a ternary expression is:
useEffect(() => {
Firebase
.firestore
.collection("blog")
.doc(slug)
.get()
.then(function(doc) {
doc.exists? setCurrentPost(doc.data()) : console.log("No such document!")
})
.catch(function(error) {
console.log("Error getting document:", error);
}), []
})
When I try this, I get the same error message as I did when I used the if statement.
Can anyone help with an example of using useEffect to read firestore data (once) in a jsx file?
NEXT ATTEMPT Using Nicholas' suggestion, I changed the useEffect to:
useEffect(() => {
Firebase
.firestore
.collection("blog")
.doc(slug)
.get()
.then(function(doc) {
doc.exists? setCurrentPost(doc.data()) : console.log("No such document!")
.catch(function(error) {
console.log("Error getting document:", error)
})
}, [])
})
That generates an error that says:
Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
NEXT ATTEMPT
I tried Ben's suggestion - changing the object in currentPost back to an array, but I get the same error as I get when I try Nicholas' suggestion.
Then, I tried merging bits of them like this:
import React, { useHook, useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import Firebase from "../../../firebase";
const ReadBlogPost = async () => {
let { slug } = useParams();
const [loading, setLoading] = useState(true);
const [currentPost, setCurrentPost] = useState([]);
useEffect(() => {
const fetchData = async() => {
try {
const response = await Firebase.firestore
.collection("blog")
.doc(slug)
.get()
.then(function(doc) {
doc.exists? setCurrentPost(doc.data()) : console.log("No such document!")
})
} catch(err) {
console.error(err);
}
};
fetchData();
}, []);
return (
<div>
{!loading &&
currentPost.title}
</div>
)
};
export default ReadBlogPost;
I still get the same error.
Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead. in ReadBlogPost (created by Context.Consumer)
I don't know if there is a clue in this, but the ReadBlogPost reference suggests that I have a context consumer somewhere. I haven't created a context yet - so not sure if it's looking for one to be able to use useEffect?