1

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`);
  }
}
Rip Rip
  • 31
  • 5
  • you are creating an express-like route handler in api/secret. This is where the cannot read 'get' is coming from, please provide the entire code inside api/secret – Stanleyy Jan 07 '23 at 15:21

3 Answers3

1

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});
Utkarsh
  • 105
  • 4
1

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`);
  }
}
Stanleyy
  • 302
  • 3
  • 12
  • you are right, but i still have the same error @Stanleyy – Rip Rip Jan 07 '23 at 15:42
  • The error indicates that you are trying to access the 'get' property on something that results in undefined. I would suggest debugging your code, page by page, and logging any variables that use a ``.get`` or ``.get()``. Then check your console and see if any of those resolve to undefined. – Stanleyy Jan 07 '23 at 15:48
  • The 2 .get you see in my useffect are the only ones I use in all my code @Stanleyy – Rip Rip Jan 07 '23 at 15:52
  • Can I get the full context of the code, are you able to provide a github link to the repo? I mainly want to see if i can reproduce the problem – Stanleyy Jan 07 '23 at 15:54
  • yes i can do it for you @Stanleyy – Rip Rip Jan 07 '23 at 15:56
  • https://github.com/piotrowicz0105/ecommerce-cbd.git @Stanleyy – Rip Rip Jan 07 '23 at 16:09
  • where is ur orders.js? You said you the path of pages/orders. Seems like the repo is not up to date, please push all of your newest changes – Stanleyy Jan 07 '23 at 16:19
  • I'm sorry I'm a bit long I have an error when I want to commit I'm trying to do this as soon as possible @Stanleyy – Rip Rip Jan 07 '23 at 16:35
  • https://github.com/piotrowicz0105/ecommerce-cbd.git @Stanleyy I managed to add my modifications here, on the master branch – Rip Rip Jan 07 '23 at 16:54
  • the problem lies with your mongoose schema definition in Order.js, im not sure what it is but I know that the problem lies there – Stanleyy Jan 07 '23 at 17:07
  • when I put a console.log in my useffect or in api/orders the console.log is not displayed so is the useffect not running? @Stanleyy – Rip Rip Jan 08 '23 at 13:17
  • ya the problem is inside the order model, if you comment out/remove the import models/order inside the pages/order, youll see that you get a different error. This denotes that the problem is inside the model/order page. This is why the pages/order page isnt able to run at all, the error is thrown as soon as you import the order model. Im not too familiar with mongoose or mongodb so i can not be of much help here – Stanleyy Jan 08 '23 at 14:03
  • I was able to find [this](https://stackoverflow.com/questions/73302263/mongoose-y-nextjs-type-error-cannot-read-properties-of-null-reading-get) which points to the same problem but does not offer a solution unfortunately – Stanleyy Jan 08 '23 at 14:05
  • 1
    Yes I created a new post where I made it clear that it came from the model thanks for your help :) @Stanleyy – Rip Rip Jan 08 '23 at 14:05
0

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.

Rip Rip
  • 31
  • 5