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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 13:43:13