You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中点击Firebase Firestore文档如何获取ID实现帖子删除

问题根因

你遇到的Uncaught TypeError: Cannot read properties of undefined (reading 'indexOf')报错,核心原因是调用deleteDoc(doc(db, "posts", id))时,第三个参数id是undefined。Firestore SDK内部会对文档路径字符串调用indexOf方法做校验,传入undefined就会直接抛出这个错误。

虽然你在useCollectionData里配置了idField: "id",期望自动把文档ID挂到返回的post对象上,但这种隐式挂载的方式容易因为字段重名、数据加载时序问题出现取值失败,最稳妥的方案是渲染列表时显式传递文档ID。

修复步骤

1. 修改Feed组件,显式传递文档ID

把列表渲染时的Post组件调用,单独传入文档ID作为独立prop,避免从post对象解构取值的异常:

function Feed() {
  const postsRef = collection(db, 'posts');
  const qwery = query(postsRef,orderBy('createdAt'), limitToLast(25));
  const [posts] = useCollectionData(qwery, {idField: "id"});

  return (
    <main>
      {posts && posts.map(msg => (
        // 显式把文档ID作为postId prop传入,不依赖post对象里的id字段
        <Post key={msg.id} postId={msg.id} post={msg} />
      ))}
    </main>
  )
}

2. 修改Post组件,简化删除逻辑

去掉从post对象里解构id的代码,直接从props取传入的postId,同时简化冗余的DOM嵌套,去掉没必要的stopPropagation(你的帖子卡片没有绑定父级点击事件,不需要阻止冒泡),可以加上简单的错误捕获避免静默失败:

function Post(props) {
  // 从props拿显式传入的postId,不要从post里解构id
  const { postId, post } = props;
  const {text, photoURL, displayName, uploaderId} = post;

  // 抽离删除逻辑,结构更清晰
  const handleDelete = async (e) => {
    // 二次权限校验,避免异常状态下的误调用
    if (auth.currentUser?.uid !== uploaderId) return;
    try {
      await deleteDoc(doc(db, "posts", postId));
    } catch (err) {
      console.error("删除失败:", err);
      alert("帖子删除失败,请重试");
    }
  }

  return (
    <div className="post">
      <div className='msg'>
        <div className='top'>
          <img src={photoURL} alt="" />
          <sub>{displayName}</sub>
        </div>
        <hr />
        <p>{text}</p>
        {auth.currentUser?.uid === uploaderId ? (
          // 直接把点击事件绑在按钮上,不需要多余的div嵌套
          <button onClick={handleDelete} className="delete-btn">🗑️</button>
        ) : null}
      </div>
    </div>
  )
}
额外优化建议
  • 前端的权限判断只是视觉隐藏,必须搭配Firestore安全规则做后端权限校验,否则其他人可以绕过前端直接调用接口删除任意帖子,规则参考:
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /posts/{postId} {
      allow read: if true;
      allow create: if request.auth != null && request.resource.data.uploaderId == request.auth.uid;
      // 仅帖子上传者本人可以删除/修改帖子
      allow delete, update: if request.auth != null && resource.data.uploaderId == request.auth.uid;
    }
  }
}
  • 可以在删除前加confirm("确认删除这篇帖子?")二次确认,避免用户误点。

内容的提问来源于stack exchange,提问作者cavia cavia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 11:18:08