对于我们的大学项目(第四学期(,我们正在React中构建一个问答应用程序,使用MaterialUI进行造型,Firestore作为DB。
我目前正忙于显示/渲染firestore文档中的数据。
firestore集合被称为user,每个注册的用户都会得到一个以其电子邮件为ID的文档。作为字段,我们将使用姓名、姓氏、电子邮件和主题,但目前只填充电子邮件。
在我们的个人资料页面上,我们现在想显示所述用户数据(目前为电子邮件(,但在加载应用程序时,该元素为空。
import React, {useState, useEffect} from "react";
import "../App.css";
import Typography from "@material-ui/core/Typography";
import {
createStyles,
makeStyles,
Container,
Card,
CardContent,
} from "@material-ui/core";
import { PageTitle } from "../components/common";
import { db , auth} from "../firebase";
const useStyles = makeStyles((theme) =>
createStyles({
proflileCard: {
minWidth: 200,
},
spaceLG: {
paddingRight: theme.spacing(30)
},
spaceXL: {
paddingTop: theme.spacing(10),
},
})
);
function Profile() {
const classes = useStyles();
const user = auth.currentUser
const userEmail = user.email
const userRef = db.collection('user')
function displayMail(){
userRef.where("email", "==" , userEmail).get().then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
console.log(doc.id, " => ", doc.data().email);
const data = doc.data()
const mail = data.email
return mail
});
})
.catch(function(error) {
console.log("Fehler beim Abrufen des Dokuments", error)
})
}
return (
< >
<PageTitle title="Profil" />
<Card
className={classes.profileCard}
variant='outlined'>
<CardContent>
<Typography
className={classes.spaceLG}
variant='h5'>
{displayMail()}
</Typography>
</CardContent>
</Card>
</>
);
}
我缺少React或firestore功能吗?
感谢您查看我们的混乱:(
更新
我可以在与朋友交谈并阅读useState和useEffect的解释后解决这个问题。我从一个函数切换到useEffect,并用一个简单的documentSnapshot替换了querySnapshot。
这让它发挥了作用:
function Profile() {
const classes = useStyles();
const user = auth.currentUser
const userEmail = user.email
const userRef = db.collection('user').doc(userEmail)
const [mail, setMail] = useState('')
useEffect(() => {
userRef.onSnapshot(docSnapshot => {
try {
console.log(docSnapshot.id, " => ", docSnapshot.data().email);
const data = docSnapshot.data()
const mail = data.email
setMail(mail)
} catch(error) {
console.log("Fehler beim Abrufen des Dokuments", error)
}
})
}, [])
return (
<div>
<PageTitle title="Profil" />
<Card
className={classes.profileCard}
variant='outlined'
>
<CardContent>
<Typography
className={classes.spaceLG}
variant='h5'
>
Login-Data
</Typography>
<Typography>
<strong>E-Mail: </strong>{mail}
</Typography>
//[...]
</div>
)
问题是您使用的Firebase SDK就像它是同步的一样。您需要注意它的async
性质,最好使用state
来处理它。你的代码可能是这样的:
import React, { useState, useEffect } from "react";
import "../App.css";
import Typography from "@material-ui/core/Typography";
import {
createStyles,
makeStyles,
Container,
Card,
CardContent,
} from "@material-ui/core";
import { PageTitle } from "../components/common";
import { db, auth } from "../firebase";
const useStyles = makeStyles((theme) =>
createStyles({
proflileCard: {
minWidth: 200,
},
spaceLG: {
paddingRight: theme.spacing(30),
},
spaceXL: {
paddingTop: theme.spacing(10),
},
})
);
function Profile() {
const classes = useStyles();
const [mails,setMails] = useState([]);
const user = auth.currentUser;
const userEmail = user.email;
const userRef = db.collection("user");
function displayMail() {
userRef
.where("email", "==", userEmail)
.get()
.then(function (querySnapshot) {
const tempMails=[]
querySnapshot.forEach(function (doc) {
console.log(doc.id, " => ", doc.data().email);
const data = doc.data();
const mail = data.email;
tempMails.push(mail);
});
setMails(tempMails);
})
.catch(function (error) {
console.log("Fehler beim Abrufen des Dokuments", error);
});
}
return (
<>
<PageTitle title="Profil" />
<Card className={classes.profileCard} variant="outlined">
<CardContent>
<Typography className={classes.spaceLG} variant="h5">
{mails.map(m=>{
return <div>{m}</div>)})}
</Typography>
</CardContent>
</Card>
</>
);
}