如何使用React渲染firestore文档中的单个字段



对于我们的大学项目(第四学期(,我们正在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>
</>
);
}

最新更新