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?
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?
Share Improve this question edited Apr 13, 2020 at 0:43 Mel asked Apr 12, 2020 at 22:15 MelMel 2,72531 gold badges137 silver badges313 bronze badges 2- Haven't tried the link yet, but maybe u need to do .firestore()? – Eliya Cohen Commented Apr 12, 2020 at 22:19
- thanks Eliya - firestore() is defined in my config as firestore - so it's right the way it is, but thanks for taking a look – Mel Commented Apr 12, 2020 at 23:25
2 Answers
Reset to default 3When getting data using useEffect, it expects a syncronous call to be made. Asking for data from Firestore will be asyncronous, so to get around this we can add a function wrapping the firestore call called fetchData like below:
import React, { useHook, useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import Firebase from "../../../firebase";
function ReadBlogPost () {
const [loading, setLoading] = useState(true);
const [currentPost, setCurrentPost] = useState({});
let { slug } = useParams();
useEffect(() => {
const fetchData = async() => {
try {
const response = await Firebase.firestore()
.collection("blog")
.doc(slug)
.get();
console.log('response', response);
let data = { title: 'not found' };
if (response.exists) {
data = response.data();
}
setCurrentPost(data);
setLoading(false);
} catch(err) {
console.error(err);
}
};
fetchData();
}, []);
return (
<div>
{!loading && currentPost.title}
</div>
)
};
export default ReadBlogPost;
I've assumed that your currentPost might be an object instead of an array given you are asking for the title in your JSX too - and I've added the setCurrentPost after the Firestore call in fetchData. Hope this helps
Update: I have changed the setup of the ponent to a named synchronous ponent (removed the const at the top and removed the async) and I've also noted that you mentioned you changed the currentPost back to an array - please ensure it's an object as you are referencing the currentPost in the JSX as an object - I just used the code I've written above locally using my own firestore database and succesfully got the details from this useEffect. Please try copying the entire snippet above. If it doesn't work I would ask you also paste in your Firestore reference code from ../firebase that you have imported. Also please try not to mix .then.catch with try {} catch {} blocks as they are attempting to do the same thing
You have the dependency array in the wrong place. With some reformatting to highlight the issue, you're doing this:
useEffect(() => {
Firebase.firestore
//...
.catch(/*...*/), [];
});
... which is technically legal javascript, due to the ma operator. But since it's likely a mistake, your linter is pointing it out.
Instead, you should be doing this:
useEffect(() => {
Firebase.firestore
//...
.catch(/*...*/);
}, []);
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745382858a4625309.html
评论列表(0条)