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

Next.js中如何正确存储Firestore文档引用作为字段?

Firestore存储文档引用时显示为Map的问题解决

我在开发一个简单博客,想要将发布的文章与登录用户关联起来。明明创建了文档引用并打算存储为引用类型字段,但Firestore数据库里却显示成了Map格式(如图所示):

Firestore中显示为Map而非引用的用户字段

我的尝试代码

前端提交代码(发送数据到API路由)

登录用户信息存在Context中,提交文章时我尝试把用户的文档引用一起发给API:

import {useAuth} from '../../context/AuthContext';

function Page() {
  const {user} = useAuth();
  const onSubmit = async () => {
    const { title, body } = content;
    await axios.post('/api/post', {
      title, 
      slug: dashify(title), 
      body, 
      author: doc(db, 'users/' + user.uid)
    });
    setContent({title: '', body: ''}); 
  }
}

API路由处理代码(创建文章)

const handler = async (req, res) => {
    try {
        const posts = await getDocs(postsRef);
        const postsData = posts.docs.map((post) => post.data());
        if (postsData.some((post) => post.slug == "slug")) res.status(406).end();
        else {
            const newPost = await addDoc(collection(db, 'posts'), {
                ...req.body,
                createdAt: serverTimestamp(),
            });
            console.log(newPost, "post details");
            res.status(200).json({ newPost });
        }
    } catch (e) {
        console.log(e, "error occured post");
        res.status(400).end();
    }
};

export default handler;

问题原因及解决方法

核心问题是:Firestore的DocumentReference对象无法通过HTTP请求直接序列化传递,前端发送的引用对象会被转换成普通JSON对象(也就是你看到的Map),到API路由后已经不是合法的引用类型了。

解决步骤如下:

  1. 前端仅传递用户UID,不要直接传doc()创建的引用对象:
// 修改后的前端提交代码
const onSubmit = async () => {
  const { title, body } = content;
  await axios.post('/api/post', {
    title, 
    slug: dashify(title), 
    body, 
    authorUid: user.uid // 只传递用户UID
  });
  setContent({title: '', body: ''}); 
}
  1. 在API路由内创建文档引用,这样存入Firestore的就是合法的引用类型:
// 修改后的API路由代码
const handler = async (req, res) => {
    try {
        const posts = await getDocs(postsRef);
        const postsData = posts.docs.map((post) => post.data());
        // 修正slug判断逻辑,匹配当前提交的slug
        if (postsData.some((post) => post.slug === req.body.slug)) {
            return res.status(406).end();
        }
        
        // 在API侧创建用户文档引用
        const authorRef = doc(db, 'users', req.body.authorUid);
        const newPost = await addDoc(collection(db, 'posts'), {
            title: req.body.title,
            slug: req.body.slug,
            body: req.body.body,
            author: authorRef, // 存入合法的文档引用
            createdAt: serverTimestamp(),
        });
        
        console.log(newPost, "post details");
        res.status(200).json({ newPost });
    } catch (e) {
        console.log(e, "error occured post");
        res.status(400).end();
    }
};

export default handler;

另外补充原代码里的两处小问题:

  • 前端代码里page function()应为function Page()才符合React组件规范
  • API路由中判断slug的逻辑有误,原代码固定匹配字符串"slug",应改为匹配req.body.slug

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 19:20:34