NextJS动态路由[slug].js结合Mongoose获取本地MongoDB数据不生效问题
问题原因&修复方案
- 组件内变量引用错误
你在getStaticProps里返回的属性名是post,但组件渲染时直接用了未定义的myPost变量,会直接触发运行错误,导致页面无响应。 - Mongoose查询方法使用错误
PostModel.find()返回的是符合条件的文档数组,你查询单篇文章应该用PostModel.findOne(),否则拿到的post是数组,即使变量名改对也取不到title属性。 - 数据库连接缺失
Next.js的getStaticProps、getStaticPaths都是独立运行在服务端的函数,你需要确保这两个函数执行前已经完成MongoDB连接,首页可以正常查询是因为首页的getStaticProps里做了数据库连接逻辑,而[slug].js里没有处理这一步,导致查询卡住无响应。
修复步骤
首先封装复用的数据库连接工具/utils/dbConnect.js,避免每次查询重复建立连接:
import mongoose from 'mongoose' const MONGODB_URI = process.env.MONGODB_URI if (!MONGODB_URI) { throw new Error('请在环境变量中配置MONGODB_URI') } let cached = global.mongoose if (!cached) { cached = global.mongoose = { conn: null, promise: null } } async function dbConnect() { if (cached.conn) { return cached.conn } if (!cached.promise) { const opts = { bufferCommands: false, } cached.promise = mongoose.connect(MONGODB_URI, opts).then((mongoose) => { return mongoose }) } cached.conn = await cached.promise return cached.conn } export default dbConnect
然后修改你的[slug].js代码:
import PostModel from "../../backend/models/PostModel"; import dbConnect from "../../utils/dbConnect"; export async function getStaticPaths() { // 先连接数据库 await dbConnect() const allPostData2 = await PostModel.find(); const paths = allPostData2.map((post) => { return { params: { slug: post.slug } }; }); return { paths, fallback: 'blocking', // 可选配置,后续新增文章不用全量重新构建 }; } export async function getStaticProps(context) { await dbConnect() const slug = context.params.slug; // 用findOne查询单篇文档,返回对象而非数组 const myPost2 = await PostModel.findOne({ slug: slug }); return { props: { // 把Mongoose文档转为普通JSON对象,避免序列化报错 post: JSON.parse(JSON.stringify(myPost2)), }, revalidate: 10, // 可选配置,增量静态再生,10秒自动更新内容 }; } export default function PostPage({ post }) { // 变量名和传入的props对应 return ( <div> <div>{post.title}</div> <div>This is a single post page</div> </div> ); }
内容的提问来源于stack exchange,提问作者Hakan Olgun
相关产品推荐
相关产品推荐

