【发布时间】:2020-11-28 22:49:12
【问题描述】:
我正在尝试弄清楚如何通过 react hooks 从 firestore 获取数据。
对于这次尝试,我尝试按照 blog post 中的示例进行操作。
我在 firestore 的一个名为“impact_metrics”的集合中创建了一个记录。
我试图弄清楚如何使用钩子在反应中显示它。
我的清单是:
import React, { useState, useEffect } from 'react';
import {Link } from 'react-router-dom';
import Typography from '@material-ui/core/Typography';
import ImpactMetricsForm from "./Form";
import firebase, { firestore } from "../../../firebase.js";
import { makeStyles } from '@material-ui/core/styles';
import clsx from 'clsx';
import ExpansionPanel from '@material-ui/core/ExpansionPanel';
import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails';
import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
import ExpansionPanelActions from '@material-ui/core/ExpansionPanelActions';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import Chip from '@material-ui/core/Chip';
import Button from '@material-ui/core/Button';
import Divider from '@material-ui/core/Divider';
const useStyles = makeStyles((theme) => ({
root: {
width: '100%',
},
heading: {
fontSize: theme.typography.pxToRem(15),
},
secondaryHeading: {
fontSize: theme.typography.pxToRem(15),
color: theme.palette.text.secondary,
},
icon: {
verticalAlign: 'bottom',
height: 20,
width: 20,
},
details: {
alignItems: 'center',
},
column: {
flexBasis: '33.33%',
},
helper: {
borderLeft: `2px solid ${theme.palette.divider}`,
padding: theme.spacing(1, 2),
},
link: {
color: theme.palette.primary.main,
textDecoration: 'none',
'&:hover': {
textDecoration: 'underline',
},
},
}));
const Title = {
fontFamily: "'Montserrat', sans-serif",
fontSize: "4vw",
marginBottom: '2vh'
};
const Subhead = {
fontFamily: "'Montserrat', sans-serif",
fontSize: "calc(2vw + 1vh + .5vmin)",
marginBottom: '2vh',
marginTop: '8vh',
width: "100%"
};
function useImpactMetrics() {
const [impactMetrics, setImpactMetrics] = useState([])
useEffect(() => {
firebase
.firestore()
.collection("impact_metrics")
.onSnapshot(snapshot => {
const impactMetrics = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data(),
}))
setImpactMetrics(impactMetrics)
})
}, [])
return impactMetrics
}
const ImpactMetricsMenu = () => {
const impactMetrics = useImpactMetrics()
const classes = useStyles();
return (
<div style={{ marginLeft: "3vw"}}>
<Typography variant="subtitle" className="blogParagraph" style={Subhead}>Select Metrics</Typography>
<div className={classes.root}>
tet
{impactMetrics.map(impactMetric => {
return (
<ExpansionPanel defaultExpanded>
<ExpansionPanelSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1c-content"
id="panel1c-header"
>
<div className={classes.column}>
<Typography className={classes.heading}>{impactMetric.title}</Typography>
</div>
<div className={classes.column}>
<Typography className={classes.secondaryHeading}>Select trip destination</Typography>
</div>
</ExpansionPanelSummary>
<ExpansionPanelDetails className={classes.details}>
<div className={classes.column} />
<div className={classes.column}>
<Chip label="Barbados" onDelete={() => {}} />
</div>
<div className={clsx(classes.column, classes.helper)}>
<Typography variant="caption">
Select your destination of choice
<br />
<a href="#secondary-heading-and-columns" className={classes.link}>
Learn more
</a>
</Typography>
</div>
</ExpansionPanelDetails>
<Divider />
<ExpansionPanelActions>
<Button size="small">Cancel</Button>
<Button size="small" color="primary">
Save
</Button>
</ExpansionPanelActions>
</ExpansionPanel>
)
})}
</div>
sdf
</div>
);
}
export default ImpactMetricsMenu;
当我尝试这个时,我在控制台中收到一条错误消息:
onSnapshot 中未捕获的错误:FirebaseError:缺失或不足 权限。
我的 Firestore 规则有:
// impact_metrics
match /impact_metrics/{impactMetricId} {
allow read;
allow write;
}
授予此权限还需要什么?
我想知道这是否可能与调用 firebase 的时间有关,所以我尝试按照this post 中的解决方案对 firestore 进行异步调用,如下所述。这是不正确的,但我不明白为什么。
function useImpactMetrics() {
const [impactMetrics, setImpactMetrics] = useState([])
useEffect(() => {
const fetchImpactMetrics = async () => {
firebase
.firestore()
.collection("impact_metrics")
.onSnapshot(snapshot => {
const impactMetrics = await snapshot.docs.map(doc => ({
id: doc.id,
...doc.data(),
}))
setImpactMetrics(impactMetrics)
})
}, [fetchImpactMetrics])
return impactMetrics
}
下一次尝试
firestore 中有一条说明,规则系统在去年年底发生了变化。我尝试选择使用第二版并在规则中添加明确的列表权限。
我从通用入门工具包中了解到条件不是规则的强制性要求,但为了解决这个问题,我添加了它们。
新规则(包括将版本2添加到规则列表顶部)是:
// impact_metrics
match /impact_metrics/{impactMetricId} {
allow read: if true;
allow list: if true;
allow write: if true;
}
当我尝试这个时,我得到了同样的控制台错误。
【问题讨论】:
标签: reactjs firebase google-cloud-firestore react-hooks firebase-security