React组件导入Mongoose Model报错:Cannot read properties of undefined (reading 'Users')
问题描述
我尝试使用Mongoose Model从MongoDB中查询并展示用户,但将其导入profile.js组件后启动应用时,出现错误提示:
- Cannot read properties of undefined (reading 'Users')
注:该Model在API中使用一切正常,不清楚为何在组件中会出现这种情况,此前从未遇到过该错误,求问题原因及解决方法。
相关代码
connect.js
import mongoose from "mongoose"; export default async function connect(){ try{ const {connection} = await mongoose.connect(process.env.MONGODB_URL) if(connection.readyState = 1){ return Promise.resolve(true) } }catch(err){ return Promise.reject(err) } }
user.js(Mongoose Model)
import {Schema, models, model} from "mongoose"; const usersSchema = new Schema({ ... }) const Users = models.Users || model('Users', usersSchema) export default Users
profile.js(React组件)
import { useState, useEffect } from 'react' import {signOut, useSession} from 'next-auth/react' import connect from "@/database/connect" import Users from "@/database/schema/users" export default function Profile(){ const [loaded, setLoaded] = useState(false) useEffect(() => { setLoaded(true) }, []) const {data: session} = useSession() console.log(session) useEffect(() => { const userSession = session.user?.email if(session){ const checkUserInfo = async() => { const findUser = await Users.findOne({ email: session.user?.email }) console.log(findUser) } checkUserInfo() } }, []) }
问题原因与解决方法
核心原因
- Mongoose不支持浏览器环境:你在客户端组件中直接调用了Mongoose Model,而Mongoose是专为Node.js后端设计的,浏览器无法运行它的底层API。
- 未建立数据库连接:即使忽略环境问题,你在查询前也没有调用
connect()初始化数据库连接,此时models.Users会是undefined,触发Cannot read properties of undefined错误。 - 组件生命周期问题:你的useEffect依赖项为空数组,可能在session还未加载完成时就执行了查询逻辑,但这不是报错的根本原因。
解决方法
方案1:将查询逻辑移到API路由(通用推荐)
把数据库操作放在后端API路由中,前端组件通过fetch请求获取数据:
步骤1:创建API路由(以Next.js 13+ App Router为例)
在app/api/get-user/route.js中创建文件:
import connect from "@/database/connect"; import Users from "@/database/schema/users"; export async function GET(request) { await connect(); const { searchParams } = new URL(request.url); const email = searchParams.get("email"); if (!email) { return Response.json({ error: "缺少邮箱参数" }, { status: 400 }); } const user = await Users.findOne({ email }); return Response.json(user); }
步骤2:修改profile.js组件调用API
import { useState, useEffect } from 'react' import {signOut, useSession} from 'next-auth/react' export default function Profile(){ const {data: session} = useSession() const [userInfo, setUserInfo] = useState(null) useEffect(() => { async function fetchUser() { if (!session?.user?.email) return; const res = await fetch(`/api/get-user?email=${encodeURIComponent(session.user.email)}`) const user = await res.json() setUserInfo(user) console.log(user) } fetchUser() }, [session]) // 渲染逻辑示例 return ( <div> {session && <p>当前用户邮箱:{session.user.email}</p>} {userInfo && <p>用户姓名:{userInfo.name}</p>} </div> ) }
方案2:使用服务器组件(Next.js 13+专属)
将profile.js改为服务器组件,直接在服务器端完成数据库查询:
import { getServerSession } from "next-auth/next" import { authOptions } from "@/app/api/auth/[...nextauth]/route" // 替换为你的NextAuth配置路径 import connect from "@/database/connect" import Users from "@/database/schema/users" export default async function Profile(){ const session = await getServerSession(authOptions) let userInfo = null if(session?.user?.email){ await connect() userInfo = await Users.findOne({ email: session.user.email }) } return ( <div> {session ? ( <> <p>已登录:{session.user.email}</p> {userInfo && <p>用户信息:{JSON.stringify(userInfo)}</p>} </> ) : ( <p>未登录</p> )} </div> ) }
额外修复点
你的connect.js中有一个语法错误,将赋值操作=改为相等判断===:
// 原代码 if(connection.readyState = 1){ // 修改后 if(connection.readyState === 1){ return Promise.resolve(true) }
内容的提问来源于stack exchange,提问作者Viper
相关产品推荐
相关产品推荐

