Firebase座位预订系统提交异常:首次无效、二次覆盖等问题求助
React + Firebase 座位预订系统提交异常问题修复
针对你遇到的三个提交异常问题,下面是问题根源分析和修复后的完整代码:
修复后的代码
import { authService, dbService } from "myBase"; import React, { useState } from "react"; const Ticketing = () => { const [performance, selectPerformance] = useState(""); const [seat, selectSeat] = useState(""); const user = authService.currentUser; const userEmail = user?.email; // 避免未登录时的报错 const onSubmit = async (event) => { event.preventDefault(); // 基础校验:确保场次、座位、用户信息都完整 if (!performance || !seat || !userEmail) { console.log("请选择演出场次和座位,且确保已登录"); return; } try { const seatDocRef = dbService.collection(performance).doc(seat); const snapshot = await seatDocRef.get(); // 直接用查询结果判断座位状态,跳过异步state的坑 if (!snapshot.exists || !snapshot.data()?.email) { await seatDocRef.set({ email: userEmail }); console.log("预订成功"); // 正确重置状态,支持连续选座 selectPerformance(""); selectSeat(""); } else { console.log("该座位已被占用"); } } catch (error) { console.error("预订失败:", error); } }; return( <div> <div onClick={() => selectPerformance("performance-1")}> Performance 1 </div> <div onClick={() => selectPerformance("performance-2")}> Performance 2 </div> <div style={{ display: "flex", gap: "10px", marginTop: "10px" }}> <div onClick={() => selectSeat("a1")}>1</div> <div onClick={() => selectSeat("a2")}>2</div> <div onClick={() => selectSeat("a3")}>3</div> <div onClick={() => selectSeat("a4")}>4</div> </div> <div style={{ marginTop: "10px" }}> <span>当前选择:{performance} - {seat}</span> </div> <button onClick={onSubmit} style={{ marginTop: "10px" }}>提交预订</button> </div> ) }; export default Ticketing;
各问题的具体修复说明
1. 首次点击提交无效
原问题根源:React的setState是异步操作,你在调用setSeatEmail和isEmpty后立刻读取对应state值,拿到的还是更新前的旧数据,导致第一次判断逻辑错误。
修复方式:直接使用Firebase查询返回的snapshot数据做判断,跳过中间状态存储,彻底避免异步更新的时机问题。
2. 已占用座位被二次提交覆盖
原问题根源:set()方法会无条件覆盖文档内容,没有做占用校验。
修复方式:
- 前端层面:先检查座位文档是否存在、
email字段是否为空,只有满足条件才写入数据 - 后端层面(必加):在Firebase控制台配置安全规则,从底层阻止覆盖已占用座位:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /{performance}/{seat} { allow write: if !exists(resource.data.email); } } }
3. 提交后无法连续选座
原问题根源:selectPerformance()和selectSeat()未传参数,会把状态设为undefined,导致后续选座逻辑异常。
修复方式:调用状态setter时传入空字符串selectPerformance("")、selectSeat(""),正确重置选择状态,支持用户连续操作。
额外优化点
- 增加
event.preventDefault():阻止input[type="submit"]的默认表单提交行为,避免页面意外刷新 - 可选链
user?.email:防止用户未登录时出现Cannot read property 'email' of null的报错 - 基础校验:确保场次、座位、用户邮箱都完整才执行预订逻辑,减少无效请求
内容的提问来源于stack exchange,提问作者Seungho Scott Shin
相关产品推荐
相关产品推荐

