繁体   English   中英

Mongoose 和 Next.js:未处理的运行时错误 TypeError:无法读取未定义的属性(读取“令牌”)

[英]Mongoose and Next.js: Unhandled Runtime Error TypeError: Cannot read properties of undefined (reading 'Token')

我基本上定义了这个模型,就像另一个不会出错的模型; 所以我很困惑为什么它不起作用......

这是一个最小的,可重现的例子

不工作:

import mongoose from 'mongoose';

const TokenSchema = new mongoose.Schema({
  _userId: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User' },
  token: { type: String, required: true },
  createdAt: { type: Date, required: true, default: Date.now, expires: 43200 }
});




export default mongoose.models.Token || mongoose.model('Token', TokenSchema);

在职的:

import mongoose from 'mongoose';
import emailValidator from 'email-validator'
import bcrypt from 'bcrypt'

import crypto from 'crypto'

const SALT_ROUNDS = 12;

const UserSchema = new mongoose.Schema(
  {
    username: {
      type: String,
      required: true,
      trim: true,
      lowercase: true,
      index: { unique: true },
      validate: {
        validator: emailValidator.validate,
        message: props => `${props.value} is not a valid email address!`
      }
    },
    password: {
      type: String,
      required: true,
      trim: true,
      index: { unique: true },
      minlength: 7,
      maxlength: 11
    },
    roles: [{ type: 'String' }],
    isVerified: { type: Boolean, default: false },
    passwordResetToken: String,
    resetPasswordExpires: Date
  },
  {
    timestamps: true
  }
);

UserSchema.pre('save', async function preSave(next) {
  const user = this;
  if (!user.isModified('password')) return next();
  try {
    const hash = await bcrypt.hash(user.password, SALT_ROUNDS);
    user.password = hash;
    return next();
  } catch (err) {
    return next(err);
  }
});

UserSchema.methods.generatePasswordReset = function () {
  this.resetPasswordToken = crypto
    .randomBytes(20)
    .toString('hex');
  this.resetPasswordExpires = Date.now() + 3600000; // expires in an hour
};

UserSchema.methods.comparePassword = async function comparePassword(candidate) {
  return bcrypt.compare(candidate, this.password);
};



export default mongoose.models.User || mongoose.model('User', UserSchema)

我也在 Next.js 示例 repo 中关注这个示例

请帮忙! :)

我复制了您的代码,它运行良好(进入tokens集合与可能预期的token )我注意到的一件事是 createdAt 上的expires字段 - 这是createdAt字段吗? 这不是一个默认字段,所以只是好奇。 此外,您能否粘贴您遇到的确切错误,这将有助于有人跟踪问题。

{
  _userId: new ObjectId("5e1a0651741b255ddda996c4"),
  token: 'abcd123',
  createdAt: 2021-09-24T23:10:24.288Z,
  _id: new ObjectId("614e5ae04c741f91ac062530"),
  __v: 0
}

此外,在声明模型时考虑使用时间戳选项属性,因为这样可以省去设置createdAt的麻烦(并且您也可以让updatedAt自动更新)。

    token: { type: String, required: true },
  },
  {
    timestamps: true
  } 
);

显然TypeError: Cannot read properties of undefined (reading 'Token')正在发生,因为代码在客户端执行,而它打算在服务器端执行。

真正发生的是 mongoose 没有启动到数据库的连接,所以mongoose.models是未定义的。 但解决方法不是尝试启动数据库连接:

当我试图在同一个文件中定义太多东西时,我也遇到了类似的问题,也就是说......在我的情况下,我正在尝试定义可以拉入客户端代码的 Typescript 接口,但是猫鼬模型定义最终也会执行......

我读到 NextJS 做了很多工作来拆分发送到客户端的代码以及保留在服务器端的代码......开发人员应该记住这一点,并尝试拆分与客户端和服务器端到不同的文件。

就我而言,我将接口定义和我的自定义 Hooks 放在与 Mongoose Schema 定义不同的文件中; 然后在我需要的时候只导入接口和钩子,这使得错误消失了。

试图将所有东西都放在同一个地方听起来合乎逻辑且整洁,但在这种情况下不起作用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM