skip to Main Content

I’m developing a NextJS app with Mongoose.

And I get a "Cannot read properties of null (reading 'get')" error when I try to use my models from Mongoose.

Here is a screenshot of the error:


Error


I’ve checked that I’ve imported my models correctly and initialized Mongoose correctly, but I can’t find the cause of this error.

models/Order.js :

import {model, models, Schema} from "mongoose";
import mongoose from 'mongoose';

const OrderSchema = new mongoose.Schema({
  products: {
    type: Object,
    required: true,
  },
  user_id: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "User",
  },
  name: {
    type: String,
    required: true,
  },
  email: {
    type: String,
    required: true,
  },
  address: {
    type: String,
    required: true,
  },
  city: {
    type: String,
    required: true,
  },
  paid: {
    type: Number,
    default: 0
  },
}, {timestamps: true});

const Order = models?.Order || model('Order', OrderSchema)

export default Order;

models/User.js:

import {model, models, Schema} from "mongoose";

const UserSchema = new Schema( {
  email:{
    type:String,
    required:true,
    unique:true,
  },
  password:{
    type:String,
    required:true,
  }
});

const User = typeof models === 'object' ? models.User : model('User', UserSchema);

export default User ;

And front side I call my data in pages folder of nextjs
pages/orders.js:

import { useEffect, useState } from "react";
import axios from "axios";
import jwt from "jsonwebtoken";
import cookie from "cookie";
import Order from "../models/Order";


function Orders() {
  const [orders, setOrders] = useState([]);
  

  useEffect(() => {
    async function fetchOrders() {
      const res = await axios.get("/api/secret");
      const secret = res.data.secret;
      // Get the JWT token from the cookies
      const token = cookie.parse(document.cookie).OursiteJWT;
      const decoded = jwt.verify(token, secret);
      const userId = decoded._id
      // Fetch the orders for the user from the backend API
      const response = await axios.get(`/api/orders?user_id=${userId}`);
      const orders = response.data;


      // Populate the user_id field in each order with the associated user object
      const populatedOrders = await Promise.all(orders.map(async (order) => {
        return await Order.findById(order._id).populate("user_id");
      }));

      setOrders(populatedOrders);
    }

    fetchOrders();
  }, []);

  return (
    <div>
      {orders.map((order) => (
        <div key={order._id}>
          <h2>Commande {order._id}</h2>
          <p>Utilisateur: {order.user_id.name}</p>
          <p>Adresse: {order.address}</p>
          <p>Ville: {order.city}</p>
          <p>Produits:</p>
          <ul>
            {order.products.map((product) => (
              <li key={product._id}>{product.name}</li>
            ))}
          </ul>
        </div>
      ))}
    </div>
  );
}

export default Orders;

api/orders :

/* eslint-disable import/no-anonymous-default-export */
import Order from "../../models/Order";
import {initMongoose} from "../../lib/mongoose";


initMongoose()

export default async function(req, res) {
  // Get the user ID from the query string
  const userId = req.query.user_id;

  // Find the orders for the user
  const orders = await Order.find({ user_id: userId }).populate("user_id");

  // Send the orders as the response
  res.json(orders);
};

api/secret :

export default async function handler(req, res) {
  const { method } = req;

  if (method === 'GET') {
    res.json({ secret: process.env.SECRET });
  } else {
    res.setHeader('Allow', ['GET']);
    res.status(405).end(`Method ${method} Not Allowed`);
  }
}

3

Answers


  1. Chosen as BEST ANSWER

    mongoose is server-side package. you cannot use the Order model inside client components. You can use models with server-side code, inside api functions or getServerSide functions.


  2. The Order Schema should be –

    const OrderSchema = new mongoose.Schema({
      products: {
        type: Object,
        required: true,
      },
      user_id: {
        type: mongoose.Schema.Types.ObjectId,
        ref: "User",
      },
      name: {
        type: String,
        required: true,
      },
      email: {
        type: String,
        required: true,
      },
      address: {
        type: String,
        required: true,
      },
      city: {
        type: String,
        required: true,
      },
      paid: {
        type: Number,
        default: 0
      },
    }, {timestamps: true});
    
    Login or Signup to reply.
  3. You are trying to create an express route handler inside a Next.js route handler. Refactor the code in api/secret to this:

    export default async function handler(req, res) {
      res.json({ secret: process.env.SECRET })
    }
    

    If you also want this route to follow the REST protocol and only allow a GET request to be accepted, you can use the following:

    export default async function handler(req, res) {
      const { method } = req;
    
      if (method === 'GET') {
        res.json({ secret: process.env.SECRET });
      } else {
        res.setHeader('Allow', ['GET']);
        res.status(405).end(`Method ${method} Not Allowed`);
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search