尝试从Firestore提取和更新Collection时,发现“ Document Collection中未定义”

时间:2019-11-27 08:54:06

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

我仍然是新手,仍在使用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;
    }
   }
  }
 }

请给我一些建议

2 个答案:

答案 0 :(得分:0)

首先,如果要测试Firestore规则,则有一个不错的选择(Firestore模拟器,您可以在firebase consol中找到它),可以在其中指定许多不同的参数并测试是否可以访问数据还是不基于特定情况。

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

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

尝试一下:

async function EditProduk({ match }) {

...

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

答案 1 :(得分:0)

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

以及

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