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

使用setDoc时Firestore无法接收数据的问题排查求助

Firestore setDoc无法更新数据排查方案

next-auth已通过Firestore Adapter正常创建用户记录,但自定义代码调用setDoc时无报错、数据库无更新,但onClick事件可触发。以下是具体排查方向和解决方法:

排查与修复步骤

1. 避免Firebase实例重复初始化

next-auth的Firestore Adapter和自定义Firebase配置可能重复初始化App,导致操作指向不同实例。

  • 修改/firebase/config.js,添加实例存在性检查:
import { initializeApp, getApp, getApps } from "firebase/app";
// ...
const app = !getApps().length ? initializeApp(firebaseConfig) : getApp();

2. 验证用户ID与文档路径匹配

确认session.user.id和Firebase控制台users集合的文档ID完全一致:

  • 打印userId值对比控制台文档ID,若不匹配,检查next-auth的session回调是否正确传递用户ID。

3. 修正setDoc的数据结构

当前代码会把数据嵌套在values字段下,若期望直接写入顶级字段,修改setDoc调用:

// 原代码:setDoc(docRef, { values }, { merge: true })
setDoc(docRef, values, { merge: true })

4. 规范异步函数处理

SignupSubmit是async函数,建议统一用await处理异步操作,避免未等待完成就结束:

try {
  await setDoc(docRef, values, { merge: true });
  console.log("文档更新成功");
} catch (error) {
  console.error("更新失败:", error);
}

同时确认调用SignupSubmit的地方是否用await等待执行完成。

5. 检查Firebase安全规则

前端Firestore默认静默处理权限拒绝,临时测试开发环境规则:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read, write: if request.auth.uid == userId;
    }
  }
}

验证正常后再调整为符合业务需求的严格规则。

6. 确认客户端环境变量加载

Next.js客户端环境变量需以NEXT_PUBLIC_开头,修改.env文件:

NEXT_PUBLIC_FIREBASE_API_KEY=xxx
NEXT_PUBLIC_FIREBASE_APP_ID=xxx
# 其他Firebase变量同理添加前缀

注:next-auth服务端用的环境变量无需前缀。


相关代码

/firebase/config.js

import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getStorage } from "firebase/storage";

const firebaseConfig = {
  apiKey: process.env.FIREBASE_API_KEY,
  appId: process.env.FIREBASE_APP_ID,
  authDomain: process.env.FIREBASE_AUTH_DOMAIN,
  databaseURL: process.env.FIREBASE_DATABASE_URL,
  projectId: process.env.FIREBASE_PROJECT_ID,
  storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
};

const app = initializeApp(firebaseConfig);

const storage = getStorage(app);
const db = getFirestore(app);

export { storage, db };

/components/signup/SignupSubmit.js

import { getSession } from "next-auth/react";
import { setDoc, doc } from "firebase/firestore";
import { db } from "../../firebase/config";

export default async function SignupSubmit(value) {
  const session = await getSession();
  const userId = session.user.id;

  const values = {
    profile: value.profile,
    screenName: value.screenName,
  };

  const docRef = doc(db, "users", `${userId}`);
  console.log(docRef);

  setDoc(docRef, { values }, { merge: true })
    .then(() => {
      console.log("Document has been updated successfully");
    })
    .catch((error) => {
      console.log(error);
    });
}

/pages/_app.js

import React from "react";
import { SessionProvider } from "next-auth/react";
import { SWRConfig } from "swr";

import Layout from "../components/Layout.js";
import AccountSettingsLayout from "../components/AccountSettingsLayout";

import "../styles/globals.css";

export default function App({ Component, router, pageProps }) {
  if (router.pathname.startsWith("/auth/")) {
    return (
      <React.StrictMode>
        <SessionProvider session={pageProps.session}>
          <SWRConfig>
            <AccountSettingsLayout>
              <Component {...pageProps} />
            </AccountSettingsLayout>
          </SWRConfig>
        </SessionProvider>
      </React.StrictMode>
    );
  }

  return (
    <React.StrictMode>
      <SessionProvider session={pageProps.session}>
        <SWRConfig>
          <Layout>
            <Component {...pageProps} />
          </Layout>
        </SWRConfig>
      </SessionProvider>
    </React.StrictMode>
  );
}

/pages/api/auth/[...nextauth].js

import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import EmailProvider from "next-auth/providers/email";
import { FirestoreAdapter } from "@next-auth/firebase-adapter";

const authOptions = {
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_ID,
      clientSecret: process.env.GOOGLE_SECRET,
    }),
    EmailProvider({
      server: {
        host: process.env.EMAIL_SERVER_HOST,
        port: process.env.EMAIL_SERVER_PORT,
        auth: {
          user: process.env.EMAIL_SERVER_USER,
          pass: process.env.EMAIL_SERVER_PASSWORD,
        },
      },
      from: process.env.EMAIL_FROM,
    }),
  ],
  session: {
    jwt: false,
  },
  adapter: FirestoreAdapter({
    apiKey: process.env.FIREBASE_API_KEY,
    appId: process.env.FIREBASE_APP_ID,
    authDomain: process.env.FIREBASE_AUTH_DOMAIN,
    databaseURL: process.env.FIREBASE_DATABASE_URL,
    projectId: process.env.FIREBASE_PROJECT_ID,
    storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
    messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
  }),
  theme: {
    colorScheme: "dark",
  },
  pages: {
    signIn: "/auth/signin",
    newUser: "/auth/signup",
  },
  debug: false,
  callbacks: {
    async signIn({ user, account, profile }) {
      if (account.provider === "google") {
        return profile.email_verified;
      }
      return true;
    },
    async redirect({ url, baseUrl }) {
      return baseUrl;
    },
    async session({ session, user }) {
      session.user.id = user.id;
      return Promise.resolve(session);
    },
    async jwt({ token, user, account, profile, isNewUser }) {
      return token;
    },
  },
};
export default NextAuth(authOptions);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 08:40:31