Tips for creating a POST request using mongoose in NextJS version 13.4

Currently, I am faced with the challenge of executing a POST request using mongoose in NextJS. In my project structure, I have three key files: lib/dbConnect.js, models/User.js, and app/new/route.ts. As defined, app/new/route.ts is responsible for handling the form page where the POST request will be initiated. Let's take a closer look at my lib/dbConnect.js:

import mongoose from 'mongoose'

const MONGODB_URI = process.env.MONGODB_URI

if (!MONGODB_URI) {
  throw new Error(
    'Please define the MONGODB_URI environment variable inside .env.local'
  )
}

/**
 * To ensure connection persistence across hot reloads in development,
 * we utilize "Global" to maintain a cached connection.
 */
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
    })
  }

  try {
    cached.conn = await cached.promise
  } catch (e) {
    cached.promise = null
    throw e
  }

  return cached.conn
}

export default dbConnect;

Moving on to models/User.js:

import mongoose from 'mongoose'

/* UserSchema maps to a designated collection in MongoDB database */
const UserSchema = new mongoose.Schema({
  name: {
    /* User's name */

    type: String,
    required: [true, 'Please provide your name.'],
    maxlength: [60, 'Name cannot exceed 60 characters'],
  },
  email: {
    /* User's email address */

    type: String,
    required: [true, "Please provide your email."],
    maxlength: [60, "Email cannot exceed 60 characters"],
  },
  password: {
    /* User's password */

    type: String,
    required: [true, 'Please provide your password.'],
    maxlength: [60, 'Password must not exceed 40 characters'],
  },
  // dob: {
  //   /* User's DOB */

  //   type: Date,
  //   required: true,
  // },
  country: {
    /* User's country */

    type: String,
    required: [true, 'Please provide your country.'],
    maxlength: [60, 'Country must not exceed 40 characters'],
  },
})

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

Admittedly, I'm struggling with defining app/new/route.ts and implementing the POST request within it. Resources online haven't provided sufficient guidance. While some references mention middleware utilization, I've yet to decipher how to incorporate this into my existing dbConnect.js file.

Answer №1

Does your app/new/route.ts file resemble the following structure?

import User from "models/User.js";
import dbConnect from "lib/dbConnect.js";
import { NextRequest, NextResponse } from 'next/server';

dbConnect()

export async function POST(request: NextRequest) {
    try {
        const reqBody = await request.json()
        const { username, email, password } = reqBody

        const newUser = new User({
            username,
            email,
            password: hashedPassword
        })

        const savedUser = await newUser.save()

        return NextResponse.json({
            message: "User created successfully",
            sucess: true,
            savedUser
        }

    } catch(err) {

     console.log(err)
    }

}

If you are looking for an alternative to route.ts, consider leveraging NextJS's Server Actions for database requests. However, this approach may necessitate additional clarity on the client or server side integration.

An example of this concept could be implemented in a file like lib/user.action.ts:

import User from "models/User.js";
import dbConnect from "lib/dbConnect.js";

export async function updateUser() {

   dbConnect()

   try {
        await User.findOneAndUpdate(
            {
                email: email.toLowerCase(),
                name,
                password,
                country
            },
            { upsert: true }
        )

 
    } catch (error) {
        throw new Error(`Failed to create/update user: ${error.message}`)
    }

} 

Answer №2

My version of route.ts ended up being located in app/api/users/route.ts. Below is the code inside this file:

import { IncomingRequest, OutgoingResponse } from "next/server";
import dbConnect from '../../../lib/dbConnect'
import User from '../../../models/User'

export async function POST(req: IncomingRequest, res: OutgoingResponse) {
    const data = await req.json();
    await dbConnect();

    try {
        const user = await User.create(
            data
        ) /* creating a new model in the database */
        return OutgoingResponse.json({
            success: true,
            data: user,
            message: "Success"
        }, {
            status: 201,
        })
    } catch (error) {
        return OutgoingResponse.json({
            success: false,
            message: "Fail",
        }, {
            status: 400,
        })
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

While interacting with router.query, certain characters may be omitted, however they still persist in the URL

Utilizing router.query, I fetch the necessary token for users to update their passwords. However, when I display it in my hidden field, characters such as + and / are removed. Despite attempting to use encodeURIComponent to address this issue, it does not ...

The callback function inside the .then block of a Promise.all never gets

I'm currently attempting to utilize Promise.all and map in place of the forEach loop to make the task asynchronous. All promises within the Promise.all array are executed and resolved. Here is the code snippet: loadDistances() { //return new Prom ...

Can the conventional HTML context menu be swapped out for a link context menu instead?

Currently, I am working on developing a custom linkbox component that is similar to the one found on this page: Here is an example of the code: export const Linkbox = ({}) => { const linkRef = useRef(null); return ( // eslint-disable-next-l ...

JWT authentication for restricted routes

I'm currently developing an application that requires users to log in and allows them to join private groups. I have successfully implemented the login part using JWT, but I'm struggling with how to prevent users from joining private groups until ...

Determine the total number of connections in a mongoose database that meet a

I am working with two schemas: Vehicle schema : const VehicleSchema = new Schema({ title: { type: String, required: true }, price: { type: Number, required: true }, ); VehicleSchema.virtual('booking', { ref: 'Booking&ap ...

The useEffect hook in React is signaling a missing dependency issue

Any tips on how to resolve warnings such as this one src\components\pages\badge\BadgeScreen.tsx Line 87:6: React Hook useEffect has a missing dependency: 'loadData'. Either include it or remove the dependency array react-hoo ...

Discovering a specific element using jQuery

I am trying to work with a div structure like this: <div class="country"> <div class="cty_popover"> <p>TITLE</p> <ul> <li>NAME 1</li> <li>NAME 2</li> ...

Error message: Requesting server-side file requires JavaScript to be enabled

This issue has been quite a challenge for me, as it appears to be straightforward but has turned into a complex problem. I have a vue application that utilizes canvas to draw images. I want an API to determine the 'type' of image to display (fil ...

Avoid updating the input from ng-model while it is being edited

There are times when my model.field can be altered by both user input into an input field and by other functions running in the background. However, I want to handle situations where changes made by the user take precedence over modifications made by those ...

What is the best way to deduct a variable's previous value from the final value, ensuring that the total value does not surpass a specific limit?

For instance: let num = 20; const sub = 6; const add = 10; num = num - sub; num = num + add; if (num > 20){ num = 20; } console.log("Only 6 was actually added to var num before reaching its maximum value"); Is there a way to adjust the console log ...

Error in AngularX TS: Trying to invoke a type that does not have a callable signature

Encountering an issue while working on a component, specifically during ng serve/build process. Please note that this error is different from any console errors, despite what some may think. The expected outcome is for the code to successfully build and ru ...

Display the menu and submenus by making a request with $.get()

My menu with submenu is generated in JSON format, but I am facing issues displaying it on an HTML page using the provided code. Can someone please assist me in identifying what mistakes I might be making? let HandleClass = function() { ...

Steps to show a particular row in a Vue.js API

I have a question about how to retrieve data from an API and display it in a textbox when the edit button on a specific row table is clicked. The data should include its own id along with other details. I apologize for sharing my code in this format, as I ...

Searching for a value within a intricate array structure

Within the course collection, I have a specific document that looks like this: { "_id" : ObjectId("53580ff62e868947708073a9"), "startDate" : ISODate("2014-04-23T19:08:32.401Z"), "scoreId" : ObjectId("531f28fd495c533e5eaeb00b"), "rewardId" : n ...

Utilizing AngularJS: Binding stateParams value to custom data within state objects

Following the guidelines here, I am setting a page title in my state object. $stateProvider .state('project', { url: '/projects/:origin/:owner/:name', template: '<project></project>', data : { pageTi ...

Discovering the method for accessing nested JSON data through ng-repeat in AngularJS

I'm attempting to access the items._id value within ng-view using ng-repeat. I am able to retrieve all data, but I am interested in specific data only. Data.json [ { _id : "td6v9db4514cc4ewew4334", firstName : 'ayaz', la ...

Express encountered an issue when trying to upload a file through AngularJS

I am currently facing an issue with uploading a file to express and subsequently to mongoDB. Despite my efforts, when I attempt to upload the file to express, it appears that no data is being passed through the response. I am utilizing ng-file-upload.min. ...

Iterate through the JSON data values using a loop and showcase each one by presenting them in individual cards

I'm having trouble determining which type of loop to use in this situation because I am still learning jQuery and JS. On the result page, I have set up cards to separate each piece of data from the JSON file, but I am unsure how to actually display th ...

The tool tip feature is not recognizing line breaks

I've encountered an issue with the tooltip in my project. Despite trying various solutions found on stackoverflow, I am still unable to resolve it. In my ReactJS application, I am dynamically creating elements using createElement and applying the too ...

Unable to display a custom image as a check mark on a checkbox

I tried to add some custom CSS to style the images on my checkmark boxes. The goal was to display an image with a checkmark when clicked, but unfortunately, it's not working as expected during testing. For this task, I utilized CSS and HTML from a he ...