【问题标题】:Found "Undefined in Document Collection" when try to fetch and update Collection from Firestore尝试从 Firestore 获取和更新集合时发现“文档集合中未定义”
【发布时间】:2020-03-22 18:49:16
【问题描述】:

我还是新手,还在使用 react 和 firebase 进行自学,请帮我处理这段代码。

我尝试使用带有 react 和 material-ui 的表单从 firestore 收集数据 获取和更新数据 ,

在我更新 useEffect 函数后,没有发现错误,只是没有按我的预期工作。

attached file firestore location picture

  import React, { useState, useEffect } from 'react';

 // material-ui
 import TextField from '@material-ui/core/TextField';
 import Button from '@material-ui/core/Button';
 import Grid from '@material-ui/core/Grid';
 import Typography from '@material-ui/core/Typography';

// firebase
 import { useFirebase } from '../../../components/FirebaseProvider';
 import { useDocument } from 'react-firebase-hooks/firestore';

import AppPageLoading from '../../../components/AppPageLoading';
import { useSnackbar } from 'notistack';

函数

function EditProduk({ match }) {

const { firestore, user } = useFirebase();
const { enqueueSnackbar } = useSnackbar();
const produkTraining = firestore.doc(`userdoc/${user.uid}/training/${match.params.trainingId}`);

const [snapshot, loading] = useDocument(produkTraining);

const [form, setForm] = useState({
    name: '',
    trainer: '',
    price: 0,
    description: ''
});

const [error, setError] = useState({
    name: '',
    trainer: '',
    price: '',
    description: ''
})

const [isSubmitting, setSubmitting] = useState(false);

useEffect(() => {
    if (snapshot) {

        setForm(currentForm => ({
            ...currentForm,
            ...snapshot.data()
        }));
    }
}, [snapshot]);

const handleChange = e => {

    setForm({
        ...form,
        [e.target.name]: e.target.value
    })

    setError({
        ...error,
        [e.target.name]: ''

    })
}

const validate = () => {
    const newError = { ...error };

    if (!form.name) {
        newError.name = 'Training name must be filled';
    }
    if (!form.trainer) {
        newError.trainer = 'trainer name must be filled';
    }
    if (!form.price) {
        newError.price = 'price must be filled';
    }
    if (!form.description) {
        newError.description = 'description must be filled';
    }
    return newError

}


const handleSubmit = async e => {
    e.preventDefault();

    const findErrors = validate();

    if (Object.values(findErrors).some(err => err !== '')) {
        setError(findErrors);
    } else {
        setSubmitting(true);
        try {
            await produkTraining.set(form, { merge: true });
            enqueueSnackbar('Data has been saved', { variant: 'success' })
        }
        catch (e) {
            enqueueSnackbar(e.message, { variant: 'error' })
        }
        setSubmitting(false);
    }

}

if (loading) {
    return <AppPageLoading />
}

return <div>
    <Typography variant="h5" component="h1">Edit Training: {form.name}</Typography>
    <Grid container alignItems="center" justify="center">
        <Grid item xs={12} sm={6}>
            <form id="produk-form" onSubmit={handleSubmit} noValidate>
                <TextField
                    id="name"
                    name="name"
                    label="Training Name"
                    margin="normal"
                    required
                    fullWidth
                    value={form.name}
                    onChange={handleChange}
                    helperText={error.name}
                    error={error.name ? true : false}
                    disabled={isSubmitting}
                />

firestore 规则

 service cloud.firestore {
  match /databases/{database}/documents {
   match /userdoc/{uid} {
    allow read: if request.auth.uid == uid;
    allow write: if request.auth.uid == uid;

    match /training/{trainingId}{
    allow read, write: if request.auth.uid == uid;
    }
   }
  }
 }

请给我一些建议

【问题讨论】:

标签: reactjs firebase google-cloud-firestore firebase-security


【解决方案1】:

首先,如果你想测试firestore规则,有一个很好的选择(firestore模拟器,你可以在firebase consol中找到它)你可以在其中指定很多不同的参数并测试你是否可以访问数据或不基于特定场景。

据我了解,您希望从 firestore 获取数据,将其放入表单,可能会编辑数据并将其保存回数据库。

您收到的错误与 firestore 或其规则无关,因为目前似乎未定义 form 变量。

试试这个:

async function EditProduk({ match }) {

...

const [snapshot, loading] = await useDocument(trainingDoc);

【讨论】:

  • 是的,先生,我想从 Firestore 中获取数据,将其放入表单中,可能会编辑数据并将其保存回数据库
  • @jawara 我认为问题在于你不会等待 useDocument,所以我猜在那一行之后,useEffect 会将表单变量设置为未定义。为此使用异步操作。
【解决方案2】:

要消除错误,您需要将value={form.name} 替换为value={form &amp;&amp; form.name &amp;&amp; form.name}

还有

useEffect(() => {
    if (snapshot.exists) {
        setForm(snapshot.data());
    }
}, [snapshot]);

【讨论】:

  • 获取数据是一个单独的问题。为了帮助解决这个问题,请打开一个新问题并向我们展示 useFirebase()useDocument() 如何工作并记录 match.params.trainingId,以便我们知道这是一个有效的参考。
  • 我说你是对的先生,但我仍然没有找到解决方案,你可以看到我附上的图片,不是针对 ID 集合,而是使用“未定义”集合 ID 创建一个新的集合 ID
  • 您刚刚更改了整个问题?那不酷。如果我回答了您的原始问题,请授予我答案并打开一个新问题。你不能只是不断地改变你的问题,所有的回答对于以后阅读这篇文章的任何人来说都是断章取义的。我不赞成。
猜你喜欢
  • 2018-04-09
  • 2022-01-21
  • 2018-04-04
  • 2020-08-25
  • 2021-05-12
  • 2019-11-13
  • 2020-04-15
  • 2023-03-18
  • 2018-04-03
相关资源
最近更新 更多