【问题标题】:Mongoose and Next.js: Unhandled Runtime Error TypeError: Cannot read properties of undefined (reading 'Token')Mongoose 和 Next.js:未处理的运行时错误 TypeError:无法读取未定义的属性(读取“令牌”)
【发布时间】:2022-04-16 09:54:31
【问题描述】:

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

这是Minimal, Reproducible Example

不工作:

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 示例存储库中关注此 example

请帮忙! :)

【问题讨论】:

  • 你解决了这个问题吗?我遇到了同一个...
  • @andrewnosov 嘿,我做到了——查看我的仓库,here 如果该语法不适合您,请告诉我。它也可能是一个版本的东西。 !干杯!
  • 谢谢!我通过将直接使用的函数代码移动到请求文件来解决我的问题。不知道这是如何工作的,但问题消失了。

标签: javascript mongodb mongoose next.js mongoose-schema


【解决方案1】:

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

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

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

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

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

试图把所有东西都放在同一个地方听起来合乎逻辑和整洁,但在这种情况下是行不通的。

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

    • 那我输入的对吗?
    • 怎么会这样?
    • 你遇到什么错误,或者事情没有保存?你安装的是什么版本的猫鼬?
    • 好吧,我收到了这个错误TypeError: Cannot read properties of undefined (reading 'Token') ,它混淆了 UI,所以我什么也做不了。我正在使用猫鼬6.0.7
    【解决方案3】:

    我有同样的错误。即使我的架构文件是正确的。问题是由于某种原因,我一直在将模型导入反应组件文件中

     import room from "../models/room";
    

    【讨论】:

      猜你喜欢
      • 2022-12-21
      • 2021-12-10
      • 2021-11-05
      • 2019-10-31
      • 2023-01-19
      • 2018-03-07
      • 1970-01-01
      • 2021-12-13
      • 1970-01-01
      相关资源
      最近更新 更多