使用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
相关产品推荐
相关产品推荐

