Next.js表单无法向Firebase写入数据问题求助
问题:Next.js表单无法写入Firebase数据库(无报错)
我正在学习用Next.js搭建带提交表单的简易网站,但无法将表单数据写入Firebase数据库。之前用React.js实现过相同功能且成功运行,现在Chrome控制台和网络面板都没有报错,但数据就是写不进去。
相关代码
service/index.js
import {initializeApp} from "firebase/app"; import {getFirestore} from "firebase/firestore"; const firebaseConfig = { apiKey: process.env.NEXT_PUBLIC_APIKEY, authDomain: process.env.NEXT_PUBLIC_AUTHDOMAIN, projectId: process.env.NEXT_PUBLIC_PROJECTID, storageBucket: process.env.NEXT_PUBLIC_STORAGEBUCKET, messagingSenderId: process.env.NEXT_PUBLIC_MESSAGINGSENDERID, appId: process.env.NEXT_PUBLIC_APPID, measurementId: process.env.NEXT_PUBLIC_MEASUREMENTID, } // Initialize Firebase const app = initializeApp(firebaseConfig); // Initialize Cloud Firestore and get a reference to the service export const db = getFirestore(app);
Booking页面组件
"use client" import React, {useState} from "react"; import "@styles/booking.css"; import {collection, addDoc} from "firebase/firestore"; import { db } from "@service/index"; function Booking() { const [username, setUsername] = useState(""); const [number, setNumber] = useState(""); const [email, setEmail] = useState(""); const [dropdownSelect, setDropdownSelect] = useState (""); const [userText, setUserText] = useState(""); function handleForm(e) { e.preventDefault(); const Bookings = collection(db, "bookings"); addDoc(Bookings, { formName: username, formNumber: number, formEmail: email, formDrop: dropdownSelect, formText: userText, }).then(response => {console.log(response)}).catch(error => {console.log(error.message)}) } return ( <div className="bookingContainer"> <h1>Book your service today</h1> <form className="bookingForm" method="POST" onSubmit={handleForm}> <div className="formField"> <label>Name: </label> <input type="text" id="name" name="name" placeholder="Name" defaultValue={username} onChange={e => setUsername(e.target.value)}></input> </div> <div className="formField"> <label>Number: </label> <input type="text" id="number" name="number" placeholder="Number" value={number} onChange={e => setNumber(e.target.value)}></input> </div> <div className="formField"> <label>email: </label> <input type="email" id="email" name="email" placeholder="email" value={email} onChange={e => setEmail(e.target.value)}></input> </div> <div className="serviceDropDown"> <label>Choose a service: </label> <select name="serviceSelection" id="serviceSelection" value={dropdownSelect} onChange={e => setDropdownSelect(e.target.value)}> <option value="Menu A">The Caress</option> <option value="Menu B">The Meticulous</option> <option value="Menu C">The Overhaul</option> <option disabled={true} defaultValue={true}>--------------</option> <option value="wheelbuild">Wheel Building</option> <option value="frameprotect">Frame Protection</option> <option value="pedals">Pedals Service</option> <option value="other">Other (Please specify)</option> </select> </div> <textarea className="serviceText" name="userText" id="userText" placeholder="Please enter your request here." defaultValue={userText} onChange={e => setUserText(e.target.value)}></textarea> <button type="submit">Submit</button> </form> </div> ) } export default Booking;
排查与解决方案
检查Firebase安全规则
默认Firestore规则仅允许认证用户读写数据,若未配置认证或用户未登录,会导致写入失败(无前端报错)。开发环境可临时修改规则测试:rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if true; } } }注意生产环境必须改回严格的权限规则。
验证环境变量加载
确认.env.local中NEXT_PUBLIC_前缀的变量名与代码完全一致,无拼写错误。可在组件中添加日志验证:console.log("Firebase项目ID:", process.env.NEXT_PUBLIC_PROJECTID);统一表单元素绑定方式
Name输入框和文本域使用了defaultValue,其他字段用value,状态与输入值可能不同步。统一改为value绑定:// Name输入框 <input type="text" id="name" name="name" placeholder="Name" value={username} onChange={e => setUsername(e.target.value)}></input> // 文本域 <textarea className="serviceText" name="userText" id="userText" placeholder="Please enter your request here." value={userText} onChange={e => setUserText(e.target.value)}></textarea>完善错误日志
把catch中的日志改为console.error(error),查看完整错误对象;同时在提交前后添加日志,确认函数执行状态:function handleForm(e) { e.preventDefault(); console.log("提交的表单数据:", {username, number, email, dropdownSelect, userText}); const Bookings = collection(db, "bookings"); addDoc(Bookings, { formName: username, formNumber: number, formEmail: email, formDrop: dropdownSelect, formText: userText, }).then(response => {console.log("写入成功,文档ID:", response.id)}) .catch(error => {console.error("写入失败详情:", error)}) }避免Firebase重复初始化
Next.js客户端组件可能重复初始化Firebase,修改service/index.js添加初始化判断:import {initializeApp, getApps, getApp} from "firebase/app"; import {getFirestore} from "firebase/firestore"; const firebaseConfig = { // 配置信息不变 } // 仅在未初始化时创建实例 const app = getApps().length > 0 ? getApp() : initializeApp(firebaseConfig); export const db = getFirestore(app);
内容的提问来源于stack exchange,提问作者kusson
相关产品推荐
相关产品推荐

