我试图将新文档添加到文档中不存在的子集合(solutionsCollection/docID/commentsSubCollection).

类型

将新文档添加到comments个子集合的代码:

  const addSubCollectionDocument = async (docID, doc) => {
    dispatch({ type: "IS_PENDING" })
    try {
      const docRef = doc(db, c, docID)
      const colRef = collection(docRef, "comments")
      const addedDocument = await addDoc(colRef, doc)
      dispatchIfNotCancelled({ type: "ADDED_DOCUMENT", payload: addedDocument })
      return addedDocument
    } catch (error) {
      console.log(error)
      dispatchIfNotCancelled({ type: "ERROR", payload: error })
      return null
    }
  }

handleSubmit函数:

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

    try {
      const commentToAdd = {
        id: Math.floor(Math.random() * 10000),
        content: newComment.trim(),
        reactions: [],
        user: {
          userID: user.uid,
          avatarURL: user.photoURL,
          displayName: user.displayName,
          username: user.reloadUserInfo.screenName,
        },
        replies: [],
        createdAt: new Date(),
      }
      await addSubCollectionDocument(id, commentToAdd)
      setNewComment("")
      if (response) {
        console.log(response.error)
      }
    } catch (error) {
      console.log(error)
    }
  }

useFirestore钩子代码:

import { useEffect, useReducer, useState } from "react"
import {
  addDoc,
  collection,
  deleteDoc,
  doc,
  serverTimestamp,
  updateDoc,
} from "firebase/firestore"

import { db } from "../firebase/config"

export const useFirestore = (c) => {
  const [response, dispatch] = useReducer(firestoreReducer, initialState)
  const [isCancelled, setIsCancelled] = useState(false)

  // only dispatch is not cancelled
  const dispatchIfNotCancelled = (action) => {
    if (!isCancelled) {
      dispatch(action)
    }
  }

  // add a document
  const addDocument = async (doc) => {
    dispatch({ type: "IS_PENDING" })

    try {
      const createdAt = serverTimestamp()
      const addedDocument = await addDoc(collection(db, c), {
        ...doc,
        createdAt,
      })
      dispatchIfNotCancelled({ type: "ADDED_DOCUMENT", payload: addedDocument })
    } catch (err) {
      dispatchIfNotCancelled({ type: "ERROR", payload: err.message })
    }
  }

  // Add document to sub collection
  const addSubCollectionDocument = async (docID, doc) => {
    dispatch({ type: "IS_PENDING" })
    try {
      const docRef = doc(db, c, docID)
      const colRef = collection(docRef, "comments")
      const addedDocument = await addDoc(colRef, doc)
      dispatchIfNotCancelled({ type: "ADDED_DOCUMENT", payload: addedDocument })
      return addedDocument
    } catch (error) {
      console.log(error)
      dispatchIfNotCancelled({ type: "ERROR", payload: error })
      return null
    }
  }


  useEffect(() => {
    return () => setIsCancelled(true)
  }, [])

  return {
    addDocument,
    addSubCollectionDocument,
    response,
  }
}

我要导入addSubCollectionDocument个钩子的文件:

import { useFirestore } from "../../hooks/useFirestore"
import { useAuthContext } from "../../hooks/useAuthContext"

const SolutionComments = ({ solution }) => {
  const [newComment, setNewComment] = useState("")
  const { user } = useAuthContext()
  const { id } = useParams()
  const { addSubCollectionDocument, response } = useFirestore("solutions")

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

    try {
      const commentToAdd = {
        id: Math.floor(Math.random() * 10000),
        content: newComment.trim(),
        reactions: [],
        user: {
          userID: user.uid,
          avatarURL: user.photoURL,
          displayName: user.displayName,
          username: user.reloadUserInfo.screenName,
        },
        replies: [],
        createdAt: new Date(),
      }
      await addSubCollectionDocument(id, commentToAdd)
      setNewComment("")
      if (response) {
        console.log(response.error)
      }
    } catch (error) {
      console.log(error)
    }
  }

  return (...)}

包裹json要点:

Firebase规则:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
        match /challenges/{challenge}{
        allow read: if true
    }
    match /resources/{resource}{
        allow read: if true
    }
    match /solutions/{solution}{
      allow read: if true
      allow create: if request.auth.uid != null;
      allow update, delete: if request.auth.uid == resource.data.userID;
    }
    match /users/{userId}{
        allow create: if true
      allow read: if true
    }
  }
}

推荐答案

const addSubCollectionDocument = async (docID, doc) => { ... })
// That "doc" parameter is not a function      ^^^

该参数似乎是要传递给addSubCollectionDocument()的对象.try 将其重命名为其他名称,如:

const addSubCollectionDocument = async (docID, docData) => {
  const colRef = collection(db, c, docID, "comments")
  const addedDocument = await addDoc(colRef, doc)
})

您尚未为注释子集合指定安全规则.try 添加以下规则:

match /c/{docId}/comments/{commentId} {
  allow read, write: if true; 
}

请根据您的用例将if true更新为所需规则.

Javascript相关问答推荐

在forEach循环中获取目标而不是父对象的属性

如何将innerHTML字符串修剪为其中的特定元素?

是否可以在Photoshop CC中zoom 路径项?

按下单键和多值

Phaserjs-创建带有层纹理的精灵层以自定义外观

是否可以将异步调用与useState(UnctionName)一起使用

在SuperBase JS客户端中寻址JSON数据

JWT Cookie安全性

使用CEPRESS截取时,cy.Wait()在等待5000ms的第一个路由请求时超时

本地损坏的Java脚本

在单击按钮时生成多个表单时的处理状态

如何设置时间选取器的起始值,仅当它获得焦点时?

限制数组中每个元素的长度,

REACT-本机错误:错误类型错误:无法读取未定义的容器的属性

使用JavaScript或PHP从div ID值创建锚标记和链接

对象作为react 子对象无效(已找到:具有键的对象{type,props}).如果要呈现一个子级集合,请改用数组

try 导入material 时出现错误NG0203

制表机表宽度在第一次加载时缩小,拖动后正在调整

无限循环,因为变量不断被重新声明为其原始值

将数据对象代码中缺失的属性添加到单个对象不起作用