'Next.JS and Mongoose models
I'm building a pretty simple next.js app for a client and for my life I cannot figure out why I keep getting Cannot overwrite User
model once compiled.
It seems to work fine everytime I shutdown the development server for the first request to any route: addUser, authenticate, GET... it all works on the first request only. This is my connect function to MongoDB.
const connectDB = (handler) => async (req, res) => {
if (mongoose.connections[0].readyState) {
return handler(req, res);
}
await mongoose
.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
useUnifiedTopology: true,
})
.then(() => {
return handler(req, res);
});
};
const middleware = nc();
middleware.use(connectDB);
// middleware.use(authMiddleware);
module.exports = {
connectDB,
middleware,
};
and the model:
const mongoose = require("mongoose");
const bcrypt = require("bcryptjs");
const UserSchema = mongoose.Schema(
{
userName: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
},
{ timestamps: true }
);
UserSchema.pre("save", async function (next) {
if (this.isModified("password")) {
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
next();
} else {
next(new Error("failed to encrypt password"));
}
});
UserSchema.methods.comparePassword = async function (password, next) {
const comparison = bcrypt.compare(password, this.password);
if (!comparison) {
return {
isMatch: false,
comparison: comparison,
};
} else {
return {
isMatch: true,
comparison: comparison,
};
}
};
module.exports = mongoose.model("User", UserSchema);
and the route:
const handler = nc();
// handler.use(middleware);
handler.post(async (req, res) => {
console.log(colors.bgBlue("Did run in route..."));
try {
const user = await User.findOne({ userName: req.body.email });
const { isMatch } = await user.comparePassword(req.body.password);
if (!isMatch) {
return res.status(401).json({ error: "These passwords do not match." });
}
if (isMatch) {
const payload = {
user: {
id: user.id,
},
};
jwt.sign(
payload,
process.env.JWT_SECRET,
{
expiresIn: 3600,
},
(err, token) => {
if (err) throw err;
return res.json({ userID: user._id, token });
}
);
}
} catch (error) {
console.log(error);
res.status(500).json({ error: "There was an error adding that user." });
}
});
export default connectDB(handler);
Sorry for making this so long, I literally have no idea where to even start. I miss express but the SSR is pretty rad :(
Solution 1:[1]
You are overwriting User
with user
when you call comparePassword
.
Change it to User.comparePassword
Explanation: user
is your declared variable holding the returned document(s), while User
is represanting the model that you are importing \ requiring from mongoose.
Solution 2:[2]
In next.js this is how we should export the mongoose models.
export default mongoose.models.User || mongoose.model("User", userSchema);
That is why instead of common.js
you shouldbe using es-modules
import export syntax in your models file.
import mongoose from "mongoose";
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | ISAE |
Solution 2 | Yilmaz |