在 React 中渲染 Firestore 时间戳
几个月来我一直在尝试弄清楚如何在 React 中显示 Firestore 时间戳。
2019 年 12 月,我在这篇 帖子 上接受的解决方案有效。现在它不再有效。我又陷入困境了。
我有一个 firebase.js 助手来记录日期:
class Firebase {
constructor() {
app.initializeApp(config)
this.firestore = app.firestore();
this.auth = app.auth();
this.serverTimestamp = app.firestore.FieldValue.serverTimestamp;
}
我在表单中使用该助手来记录创建条目的日期,如下所示:
await Firebase.firestore.collection("blog").doc().set({
title: values.title,
createdAt: Firebase.serverTimestamp()
这样可以正确地将日期保存到 firestore 文档中,如下所示:
当我将鼠标悬停在日期上时,它会显示“时间戳”。我能够根据 createdAt 日期对从 firestore 返回的数据进行排序 - 因此奇怪的是,时间戳可用于对文档进行排序,但不能用于在屏幕上打印日期。
当输出日期时,我又回到了上一篇文章中报告的所有相同错误 - 但 12 月有效的解决方案不再有效。我在 firebase slack 频道中看到过一个讨论,说 firebase 的最新版本产生了一些意想不到的后果 - 有没有办法检查损坏的时间戳是否是其中之一?
当我尝试:
{currentPost.createdAt.toDate().toISOString()}
TypeError: Cannot read property 'toDate' of undefined
当我尝试:
{currentPost.createdAt.toDate()}
TypeError: Cannot read property 'toDate' of undefined
当我尝试:
{new Date(currentPost.createdAt.seconds * 1000).toLocaleDateString("en-US")}
TypeError:无法读取未定义的属性“seconds”
当我尝试(我知道这行不通,但只是试图找到可能有助于解决此问题的见解):
{currentPost.createdAt}
Error: Objects are not valid as a React child (found: object with keys {seconds, nanoseconds}). If you meant to render a collection of children, use an array instead.
我看到过一些 posts 表示日期未定义,因为对 firebase 的调用尚未返回值,但当我 console.log 整个 currentPost 时,我得到了 created At 的值,即:
createdAt: t seconds: 1586495818 nanoseconds: 888000000
这部分看起来可疑的是“t”。它是否代表我应该做些什么才能访问时间戳?有人知道如何调查“t”代表什么吗?
我看过 这篇文章 和 这篇文章 ,并注意到它的每个答案都表明 .toDate() 扩展应该有助于将 firestore 时间戳转换为可以输出的内容。这些解决方案都不起作用。
有人想出一个当前解决方案,允许同时保存和输出 firestore 中的日期吗?
奇怪 - 我不明白为什么或如何工作,但它确实有效。
我将 useEffect 更改为异步 - 如下所示。
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();
}, []);
然后在渲染中,我可以使用:
{!loading && new Date(currentPost.createdAt.seconds * 1000).toLocaleDateString("en-US")}
祈祷这个可以工作几个月以上。
我遇到了同样的问题。解决方案对我来说很简单,您必须首先检查时间戳是否存在。
{data.time === undefined ? (
<div>Time is not defined</div>
) : (
<div> {data.time.toDate().toLocaleTimeString("en-US")}</div>
)}
之后,您可以做任何您想做的事情。 (第一次回答任何问题,如果我犯了任何错误,请告诉我)
这对我有用:
{data.timestamp.toDate().toLocaleTimeString("en-US")}