Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Firebase:如何向不同的集合提交表单数据?_Javascript_Firebase_Google Cloud Firestore_Formik - Fatal编程技术网

Javascript Firebase:如何向不同的集合提交表单数据?

Javascript Firebase:如何向不同的集合提交表单数据?,javascript,firebase,google-cloud-firestore,formik,Javascript,Firebase,Google Cloud Firestore,Formik,我有一张表格。表单中的一个字段是字段数组-用于可重复的字段。除此字段外,所有其他表单字段都存储在单个集合(父集合)中 父集合具有字段数组的数组,该数组保存每个重复条目的值,以存储在子集合(子集合)中 在编写firestore提交时,我试图将要提交到父集合的字段与要提交到子集合的字段分开 我的尝试如下 <Formik initialValues={{ term: "", category: [], relatedTerms: [

我有一张表格。表单中的一个字段是字段数组-用于可重复的字段。除此字段外,所有其他表单字段都存储在单个集合(父集合)中

父集合具有字段数组的数组,该数组保存每个重复条目的值,以存储在子集合(子集合)中

在编写firestore提交时,我试图将要提交到父集合的字段与要提交到子集合的字段分开

我的尝试如下

<Formik
                  initialValues={{ term: "",    category: [],  relatedTerms: [],  }}
                  
                  onSubmit={(values, { setSubmitting }) => {
                     setSubmitting(true);
                     firestore.collection("glossary").doc().set({
                      term: values.term,
                      category: values.category,
                      createdAt: firebase.firestore.FieldValue.serverTimestamp()
                      }),
                      firestore.collection("glossary").doc().collection('relatedTerms').doc().set({
                        dataType: values.dataType,
                        title: values.Title,
                        description: values.description,
                        
                      })
                    .then(() => {
                      setSubmitionCompleted(true);
                    });
                  }}
  
注意,我在relatedTerms文档中注释了除title属性之外的所有内容,以便查看这是否有效

没有。表单仍然呈现,当我尝试按submit时,它只是挂起。控制台中不会生成任何错误消息,但会生成一条警告消息,说明:

0.chunk.js:141417警告:从submitForm()FirebaseError:调用函数WriteBatch.set()时捕获到未经处理的错误 无效数据。不支持的字段值:未定义(在字段中找到 (标题)

当我在谷歌上搜索这个时——从这里可以看出,在relatedTerm集合中定义父级文档id的方式可能有问题

我还想知道是否需要为每个集合分别定义和初始化初始值

当我尝试用控制台记录表单条目的值时,我可以看到一个值为title的对象被捕获。表单的初始值包括一个名为relatedTerms的数组(初始值:[])

也许我需要做一些事情,将该数组转换为其中的值,然后再尝试将其发送到firestore。我该怎么做

我链接的帖子将其分为两个步骤,但我太慢了,弄不清他们在做什么,或者我自己怎么做。奇怪的是,当我不尝试在firestore集合之间分割表单值时,这个问题就不会出现——如果我只使用一个文档,那么这里需要发生的任何事情都会在默认情况下完成

我不确定我想做的是否是firestore文档在本节中描述的。我注意到上面的添加数据示例显示了添加一个数组,而没有在提交之前采取任何步骤将数组中的项转换为数据类型。我不确定这是否是正确的查询行,因为如果我不尝试在集合之间分割数据,提交的结果很好

下一次尝试

安德烈亚斯的回答对我来说很简单。spread运算符在relatedTerms条目的submit方法中使用时工作

然而,这带来了下一个挑战——如何读取子集合数据。这部分内容让我感到困惑。我搞不懂

它说:

使用mobile/web无法检索集合列表 客户端库

这是否意味着我无法读取relatedTerms表中的值

在此之前,我能够读取relatedTerms数据数组,如下所示:

function useGlossaryTerms() {
    const [glossaryTerms, setGlossaryTerms] = useState([])
    useEffect(() => {
      firebase
        .firestore()
        .collection("glossary")
        .orderBy('term')
        .onSnapshot(snapshot => {
          const glossaryTerms = snapshot.docs.map(doc => ({
            id: doc.id,
            ...doc.data(),
          }))
          setGlossaryTerms(glossaryTerms)
        })
    }, [])
    return glossaryTerms
  }
然后:

虽然在我尝试提交表单时它没有生成任何错误,但它也没有在relatedTerms文档中创建名为glossaryId的条目。值的日志也不包括它


我已经看到了吉姆的答案。我不知道如何在单独的useEffect中使用我的glossaryTerm.id作为文档id来查找相关术语。

每次调用
doc()
,都会生成一个对随机生成的新文档的引用。这意味着您对
firestore.collection(“glossary”).doc()的第一次调用将生成一个新的ID,以及随后的调用。如果要重用文档引用,必须将其存储在变量中

const firstDocRef = firestore.collection("glossary").doc()
firstDocRef.set(...)
请稍后使用相同的变量:

const secondDocRef = firstDocRef.collection('relatedTerms').doc()
secondDocRef.set(...)

我没有足够的因果报应或任何东西来评论,所以我把我的评论放在这里

下面是用代码实现Doug解决方案的一种方法。抱歉,在advanced中出现了语法错误--我没有测试运行此代码

您可以在执行之前传递文档ID,即使提交时生成了autoID

onSubmit={(values, { setSubmitting }) => {
  setSubmitting(true);
  const newDocRef = firestore.collection("glossary").doc() // auto generated doc id saved here
  let writeBatch = firestore.batch();
  writeBatch.set(newDocRef,{
    term: values.term,
    definition: values.definition,
    category: values.category,
    context: values.context,
    createdAt: firebase.firestore.FieldValue.serverTimestamp()
  }),
  writeBatch.set(newDocRef.collection('relatedTerms').doc(),{
    dataType: values.dataType,
    title: values.title,
    description: values.description,
  })
  writeBatch.commit()
    .then(() => {
      setSubmitionCompleted(true);
    });
}}

但是在提交完成之前不会生成第一个ref?那么-我如何才能将术语表id提供给relatedTerms集合呢?我不知道你在问什么。这里有什么不符合您的期望?我有一个表单,其中包含“术语”、“定义”和“相关术语”字段。前两个字段是字符串,在词汇表集合中作为文档提交,同时还有一个relatedTerms数组。relatedTerms是一个可重复的表单字段(用户可以提交多个字段条目)。每个词汇表都会与相关词汇表文档的id一起保存在“relatedTerms”子集合中。这些术语在一个表单中完成,但是提交处理程序需要将数据发送到不同的集合。我正试图弄清楚如何提交。我的建议有什么具体的地方没有按你期望的方式工作?您看到如何为嵌套在“词汇表”下的文档生成不同的文档ID了吗?我不理解您的建议。提交时,在术语表上生成autoID。我如何捕捉它,然后在relatedTerms字段中使用它?至于常量的格式,我知道doc id在括号内,而不是在:.doc()firstDocRef之后。我不知道如何在提交处理程序中使用这些常量。Firestore(和其他基于文档的数据库)有一些技术,相对来说,可以更好地实现您想要做的事情。如果你不喜欢技术文献,我会从这里开始:。谢谢@Cehhiro的建议。我刚看了这个40分钟的视频。虽然理论上讲的是数据的结构和存储方式,但实际上并没有回答我的问题
function useGlossaryTerms() {
    const [glossaryTerms, setGlossaryTerms] = useState([])
    useEffect(() => {
      firebase
        .firestore()
        .collection("glossary")
        .orderBy('term')
        .onSnapshot(snapshot => {
          const glossaryTerms = snapshot.docs.map(doc => ({
            id: doc.id,
            ...doc.data(),
          }))
          setGlossaryTerms(glossaryTerms)
        })
    }, [])
    return glossaryTerms
  }
{glossaryTerm.relatedTerms.map(relatedTerm => (
                                
                                <Link to="" className="bodylinks" key={relatedTerm.id}>
                                 {relatedTerm.title}
                          </Link>                                   ))}
glossaryId: newDocRef.id,
    ...values.relatedTerms
const firstDocRef = firestore.collection("glossary").doc()
firstDocRef.set(...)
const secondDocRef = firstDocRef.collection('relatedTerms').doc()
secondDocRef.set(...)
onSubmit={(values, { setSubmitting }) => {
  setSubmitting(true);
  const newDocRef = firestore.collection("glossary").doc() // auto generated doc id saved here
  let writeBatch = firestore.batch();
  writeBatch.set(newDocRef,{
    term: values.term,
    definition: values.definition,
    category: values.category,
    context: values.context,
    createdAt: firebase.firestore.FieldValue.serverTimestamp()
  }),
  writeBatch.set(newDocRef.collection('relatedTerms').doc(),{
    dataType: values.dataType,
    title: values.title,
    description: values.description,
  })
  writeBatch.commit()
    .then(() => {
      setSubmitionCompleted(true);
    });
}}