Next.js 14竞价系统报错:TypeError: mongoose.models未定义
解决Next.js 14中Mongoose
models 未定义的错误 问题根源
这个错误主要来自三个点:
- 数据库连接是异步操作,你直接调用
connect()后没等连接完成就加载模型、执行查询,此时mongoose.models还没初始化 - Next.js 14服务器组件的执行流程里,全局
mongoose.models对象可能还没挂载就被访问 - 如果
Form是客户端组件(带'use client'指令),在里面导入Bid模型会导致Mongoose在浏览器环境运行——而Mongoose只支持Node.js环境
修复步骤
1. 先确保数据库连接完成再操作
修改你的页面组件,把connect()改成异步等待,避免连接未就绪就执行查询:
import React from "react"; import Item from "@/models/Item"; import Form from "./Form"; import { GetDataFromToken } from "@/helpers/GetDataFromToken"; import { connect } from "@/helpers/DBConfig"; const page = async ({ params }) => { // 必须等连接完成再继续 await connect(); const { slug } = params; const item = await Item.findOne({ _id: slug }); const user = GetDataFromToken(); return ( <div> <h1>{item?.name}</h1> <p>{item?.description}</p> <p>Starting bid: {item?.startingPrice}</p> <Form user={user.id} item={item._id} /> </div> ); }; export default page;
同时把DBConfig里的连接函数改成异步并增加状态判断:
// @/helpers/DBConfig.js import mongoose from "mongoose"; export async function connect() { // 如果已经连接,直接返回 if (mongoose.connections[0].readyState) return; try { await mongoose.connect(process.env.MONGODB_URI); } catch (error) { throw new Error("数据库连接失败:" + error.message); } }
2. 调整Bid模型的初始化逻辑
把模型判断改成基于connection.models的方式,避免访问未初始化的全局models:
import mongoose from "mongoose"; const bidSchema = new mongoose.Schema( { bidder: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true, }, item: { type: mongoose.Schema.Types.ObjectId, ref: "Item", required: true, }, price: { type: Number, required: true, }, }, { timestamps: true } ); // 改用connection.models检查,更可靠 const Bid = mongoose.connection.models.Bid || mongoose.model("Bid", bidSchema); export default Bid;
3. 客户端组件不能用Mongoose
如果你的Form是客户端组件(带'use client'),绝对不能在里面导入Bid模型。所有竞价提交的逻辑要放到API路由里:
创建app/api/bids/route.js处理提交:
import { connect } from "@/helpers/DBConfig"; import Bid from "@/models/Bid"; import { NextResponse } from "next/server"; export async function POST(req) { await connect(); const { bidder, item, price } = await req.json(); try { const newBid = new Bid({ bidder, item, price }); await newBid.save(); return NextResponse.json({ success: true, bid: newBid }); } catch (error) { return NextResponse.json({ success: false, error: error.message }, { status: 500 }); } }
然后在Form组件里用fetch调用这个API:
// Form.jsx(客户端组件) 'use client'; import { useState } from 'react'; export default function Form({ user, item }) { const [price, setPrice] = useState(''); const handleSubmit = async (e) => { e.preventDefault(); const res = await fetch('/api/bids', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ bidder: user, item, price: Number(price) }) }); const data = await res.json(); if (data.success) { alert('竞价提交成功'); setPrice(''); } else { alert('提交失败:' + data.error); } }; return ( <form onSubmit={handleSubmit}> <input type="number" value={price} onChange={(e) => setPrice(e.target.value)} placeholder="输入竞价金额" required /> <button type="submit">提交竞价</button> </form> ); }
额外提醒
所有涉及Mongoose的代码(模型导入、数据库操作)都只能放在服务器组件或API路由里,别在客户端组件里碰。
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

