如何使用 React 从 firestore 文档呈现单个字段
How to render single field from firestore document with React
对于我们的大学项目(第 4 学期),我们正在 React 中构建一个测验应用程序,使用 MaterialUI 进行样式设置并使用 Firestore 作为数据库。
我目前正在努力处理来自 firestore 文档的 displaying/rendering 数据。
firestore 集合称为用户,每个注册的用户都会获得一个以 his/her 电子邮件作为 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 并将 querySnapshot 替换为简单的 documentSnapshot。
这成功了:
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>
</>
);
}
对于我们的大学项目(第 4 学期),我们正在 React 中构建一个测验应用程序,使用 MaterialUI 进行样式设置并使用 Firestore 作为数据库。
我目前正在努力处理来自 firestore 文档的 displaying/rendering 数据。
firestore 集合称为用户,每个注册的用户都会获得一个以 his/her 电子邮件作为 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 并将 querySnapshot 替换为简单的 documentSnapshot。
这成功了:
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>
</>
);
}