我正在尝试弄清楚如何使用react useEffect从Firestore获取数据。
这是我目前的尝试。
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;
最后的空数组是一种尝试,以确保React不会用尽this post和this issue中详细说明的所有Firestore读取配额。
尝试此操作时,出现错误消息:
第19:11行:希望进行赋值或函数调用,而是看到了 表达式no-unused-expressio
文件是jsx。我已经看到this post和this,这意味着我必须将if语句转换为三元条件。
我尝试将其更改为三元表达式是
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);
}), []
})
尝试此操作时,会收到与使用if语句时相同的错误消息。
有人可以举一个使用useEffect一次读取jsx文件中的Firestore数据的示例吗?
下次尝试 根据尼古拉斯的建议,我将useEffect更改为:
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)
})
}, [])
})
这会产生一个错误,提示:
错误:对象作为React子对象无效(找到:[object 诺言])。如果您打算渲染儿童集合,请使用 而不是数组。
下一个尝试
我尝试了Ben的建议-将currentPost中的对象更改回数组,但是遇到了与尝试Nicholas的建议时相同的错误。
然后,我尝试像这样合并其中的一部分:
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;
我仍然遇到相同的错误。
错误:对象作为React子对象无效(找到:[object 诺言])。如果您打算渲染儿童集合,请使用 数组代替。 在ReadBlogPost中(由Context.Consumer创建)
我不知道是否有任何线索,但是ReadBlogPost参考建议我在某个地方有上下文使用者。我尚未创建上下文-因此不确定是否正在寻找一个可以使用useEffect的上下文?
答案 0 :(得分:1)
您的依赖项数组放置在错误的位置。通过重新格式化以突出显示该问题,您正在执行以下操作:
useEffect(() => {
Firebase.firestore
//...
.catch(/*...*/), [];
});
...由于comma operator,在技术上是合法的javascript。但是由于这可能是一个错误,所以您的短毛猫会指出这一点。
相反,您应该这样做:
useEffect(() => {
Firebase.firestore
//...
.catch(/*...*/);
}, []);
答案 1 :(得分:1)
使用useEffect获取数据时,它期望进行同步调用。从Firestore询问数据将是异步的,因此要解决此问题,我们可以添加一个包装名为fetchData的firestore调用的函数,如下所示:
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;
考虑到您也在JSX中询问标题,我假设您的currentPost可能是一个对象,而不是一个数组-并且我在fetchData中的Firestore调用之后添加了setCurrentPost。希望对您有帮助
更新:我已经将组件的设置更改为命名的同步组件(删除了顶部的const并删除了异步),并且我还注意到您提到您将currentPost改回了数组-请确保这是一个对象,因为您将JSX中的currentPost引用为对象-我刚刚使用自己的firestore数据库在本地使用了上面编写的代码,并成功地从useEffect中获取了详细信息。请尝试复制上面的整个代码段。如果它不起作用,我还会请您从导入的../firebase中粘贴Firestore参考代码。另外,请不要将.then.catch与try {} catch {}块混合使用,因为它们正试图做同样的事情