简体   繁体   中英

Cannot read properties of undefined (reading 'findOne') with React App deployed on Heroku

I am having trouble after I deployed my app (backend on Heroku and frontend on Netlify). It was working fine in localhost earlier

Problem

While I was making the API request (Login or SIgnUP) from frontEnd, it is showing me the error.

Cannot read properties of undefined (reading 'findOne')

The Heroku Log is said that it is Connected to Mongo Successfully , but still I am getting this error there.

What I guess

I had created a remote MongoDB cloud on MOngoAtlas like this, 蒙哥

And I had connected it in my db.js like this

const mongoose = require("mongoose");
//const mongoURI = "mongodb://localhost:27017/?readPreference=primary&appname=MongoDB%20Compass&ssl=false";
const mongoURI = "mongodb+srv://mohit_maroliya:Zker42FNU.buD_E@cluster0.n03hm.mongodb.net/myFirstDatabase?retryWrites=true&w=majority"

const connectToMongo = async() => {
    mongoose.connect(mongoURI, {useNewUrlParser: true}, ()=> {
        console.log("Connected to Mongo Successfully!");
    })
}

module.exports = connectToMongo;

So I think that my Mongo connection is connected but not to this database.

Also in the Google Console, it is showing Unexpected token i in JSON at position 0

Code

I am sharing the code of the files involved

Index.js

const connectToMongo = require('./db');
const express = require('express');


connectToMongo();
var cors = require('cors')
const app = express()
// const port = 5000

//to use req body 
app.use(cors())
app.use(express.json())

//Available routes
app.use('/api/auth',require('./routes/auth'));
app.use('/api/notes',require('./routes/notes'));

app.listen(process.env.PORT  , () => {
  console.log(`my-notebook backend listening at https://my-notebook-mohit.herokuapp.com:${process.env.PORT }`)
})

auth.js

const express = require("express");
const { body, validationResult } = require("express-validator");
const router = express.Router();
const { User } = require("../models/User");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const JWT_SECRET = "mohitisagood$boy";
const fecthUser = require("../middleware/fetchUser");

//ROUTE 1 :Creating a User :POST - "/api/auth/createuser"
router.post(
  "/createuser",
  [
    body("name", "Name must have at least 3 characters").isLength({ min: 3 }),
    body("email", "Enter a valid email").isEmail(),
  ],
  async (req, res) => {

    let success = false;
    //If there are errors, then return bad request + Errors
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({success, errors: errors.array() });
    }

    try {
      //Check whether email exists
      //let user;
      let user = await User.findOne({ email: req.body.email });
      console.log("user.nemail = " + user);
      if (user) {
        //console.log(user.email);
        return res.status(400).json({success, error: "Email Already Taken" });
      }

      //hashing the password here
      const salt = await bcrypt.genSalt(10);
      const secPass = await bcrypt.hash(req.body.password, salt);
      //user is created
      user = await User.create({
        name: req.body.name,
        email: req.body.email,
        password: secPass,
      });

      //passing the id as data to make jwt token
      const data = {
        user: {
          id: user.id,
        },
      };

      const authToken = jwt.sign(data, JWT_SECRET);
      //console.log(authToken)

      
      success = true;
      //res.json(user);
      res.json({success, authToken });
    } catch (error) {
      console.log(error.message);
      res.status(500).send("internal server error");
    }
  }
);

//ROUTE 2 :Authenticating a User :POST - "/api/auth/login"
router.post(
  "/login",

  body("email", "Enter a valid email").isEmail(),

  async (req, res) => {
    //If there are errors, then return bad request + Errors
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }

    const { email, password } = req.body;
    
    let success = false;

    try {
      let user = await User.findOne({ email });

      // console.log("user - "+user)

      if (!user) {
        res.status(400).json({success,error:"Login with correct credentials!"});
      }

      //compare the pwd bw 'hash of pwd entered' & 'hash from your pwdDB'
      const passwordCompare = await bcrypt.compare(password, user.password);

      if (!passwordCompare) {
        res.status(400).json({success,error:"Login with correct credentials!"});
      }
      //nodemon crashes whenever PASSWORD === NULL


      const payload = {
        user: {
          id: user.id,
        },
      };

      const authToken = jwt.sign(payload, JWT_SECRET);
      
      success = true;
      res.json({ success, authToken });
    } catch (error) {
      console.log(error.message);
      res.status(500).send("Internal Server Error");
    }
  }
);



module.exports = router;

Model (User.js)

const mongoose = require("mongoose");
const { Schema } = mongoose;

const UserSchema = new Schema({
  name: {
    type: String,
    required: true,
  },
  email: {
    type: String,
    required: true,
  },
  password: {
    type: String,
    required: true,
    validate(value) {
      if(value.length < 5) {
        throw new Error( "Minimum length is 5 characters");
      }
      else if (!value.match(/\d/) || !value.match(/[a-zA-Z]/) ) {
        throw new Error(
          "Password must contain at least one letter and one number"
        );
      }

    }
    
  },
  date: {
    type: Date,
    default: Date.now,
  },
});

const User = mongoose.model("users", UserSchema);
module.exports = User;

Login.js (frontend)

import React, { useState } from "react";
import { useHistory } from "react-router-dom";
import imgpath from "../assets/notepic.jpg";
import { motion } from "framer-motion";

const Login = (props) => {
  let history = useHistory();
  
  const [credentials, setCredentials] = useState({ email: "", password: "" });

  const onChange = (e) => {
    setCredentials({ ...credentials, [e.target.name]: e.target.value });
    //input mei value typed ho sake,jaise jaise value change ho vese-vese note me set ho jaye
  };

  const goToSignup = () => {
    history.push("/signup");
  };
  
  const handleSubmit = async (e) => {
    e.preventDefault();
    const response = await fetch(`https://my-notebook-mohit.herokuapp.com:/api/auth/login`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        email: credentials.email,
        password: credentials.password,
      }),
    });
    const json = await response.json();
    if (json.success === true) {
      //storing the authtoken
      localStorage.setItem("token", json.authToken);
      props.showAlert("User logged in successfully", "info");
      history.push("/");
    } else {
      props.showAlert("invalid Credentials", "danger");
    }
    console.log(json);
  };

  return (
    <motion.div className="container" id="manku" animate={{scale:[0.5,1]}} transition={{times:[0.1,0.4], ease:'easeInOut'}}>
      <div id="picturebody">
        <img src={imgpath} alt="note-pic" width="100%" />
      </div>
      <div id="loginbody">
        <div className="mt-3">
          <h2 className="my-3"> Login to continue</h2>
          <form onSubmit={handleSubmit} className="login-form">
            .
            .
            .
          </form>
          <div className="text-center my-5" id="bottom-text">
            mynotebook
        </div>
        </div>
      </div>
    </motion.div>
  );
};

export default Login;

Heroku Logs

2022-01-26T12:04:28.024784+00:00 heroku[web.1]: Starting process with command `npm start`
2022-01-26T12:04:29.075584+00:00 app[web.1]: 
2022-01-26T12:04:29.075596+00:00 app[web.1]: > my-notebook-backend@1.0.0 start
2022-01-26T12:04:29.075596+00:00 app[web.1]: > node index.js
2022-01-26T12:04:29.075596+00:00 app[web.1]: 
2022-01-26T12:04:29.561386+00:00 app[web.1]: my-notebook backend listening at https://my-notebook-mohit.herokuapp.com:38751
2022-01-26T12:04:29.561856+00:00 app[web.1]: Connected to Mongo Successfully!
2022-01-26T12:04:29.766495+00:00 heroku[web.1]: State changed from starting to up
2022-01-26T12:04:05.000000+00:00 app[api]: Build started by user maroliya.1@iitj.ac.in
2022-01-26T12:04:24.985213+00:00 app[api]: Release v32 created by user maroliya.1@iitj.ac.in
2022-01-26T12:04:24.985213+00:00 app[api]: Deploy c9d42533 by user maroliya.1@iitj.ac.in
2022-01-26T12:04:25.000000+00:00 app[api]: Build succeeded
2022-01-26T12:06:05.906508+00:00 heroku[router]: at=info method=OPTIONS path="/api/auth/login" host=my-notebook-mohit.herokuapp.com request_id=a4c47a5b-a85b-469e-a595-f1ed356e2373 fwd="27.56.201.36" dyno=web.1 connect=0ms service=5ms status=204 bytes=301 protocol=https
2022-01-26T12:06:06.155157+00:00 app[web.1]: Cannot read properties of undefined (reading 'findOne')
2022-01-26T12:06:06.163135+00:00 heroku[router]: at=info method=POST path="/api/auth/login" host=my-notebook-mohit.herokuapp.com request_id=02849e70-a653-4751-a6dc-de73cf7a2bf2 fwd="27.56.201.36" dyno=web.1 connect=0ms service=34ms status=500 bytes=272 protocol=https
2022-01-26T12:06:21.493881+00:00 heroku[router]: at=info method=POST path="/api/auth/createuser" host=my-notebook-mohit.herokuapp.com request_id=27e52b6b-6931-4797-9296-2a81cf1c8399 fwd="27.56.201.36" dyno=web.1 connect=0ms service=4ms status=500 bytes=272 protocol=https
2022-01-26T12:06:21.291315+00:00 heroku[router]: at=info method=OPTIONS path="/api/auth/createuser" host=my-notebook-mohit.herokuapp.com request_id=25d391ad-d14c-4999-b9da-18c1328ce0cd fwd="27.56.201.36" dyno=web.1 connect=0ms service=1ms status=204 bytes=301 protocol=https
2022-01-26T12:06:21.491373+00:00 app[web.1]: Cannot read properties of undefined (reading 'findOne')

Please Help Me because I am struggling with it for a long time.

in the website of mongodb, this is the way to connect to a database.

 async function main(){
    /**
     * Connection URI. Update <username>, <password>, and <your-cluster-url> to reflect your cluster.
     * See https://docs.mongodb.com/ecosystem/drivers/node/ for more details
     */
    const uri = "mongodb+srv://<username>:<password>@<your-cluster-url>/test?retryWrites=true&w=majority";
 

    const client = new MongoClient(uri);
 
    try {
        // Connect to the MongoDB cluster
        await client.connect();
 
        // Make the appropriate DB calls
        await  listDatabases(client);
 
    } catch (e) {
        console.error(e);
    } finally {
        await client.close();
    }
}

main().catch(console.error);

and this is the link for reference

here

i think the problem is with require/export

you can either chagnge:

const { User } = require("../models/User");

to:

const User = require("../models/User");

or you can export the user like this:

module.exports.User = User;

instead of:

module.exports = User;

I think your application setup initialization is have some problem in a race condition. Have you ever try to wrap your initialization like below.

const connectToMongo = require('./db');
const express = require('express');

const start = async () => {
  await connectToMongo();  // Need to await this Promise before listen any HTTP request
  var cors = require('cors')
  const app = express()
  // const port = 5000

  //to use req body
  app.use(cors())
  app.use(express.json())

  //Available routes
  app.use('/api/auth',require('./routes/auth'));
  app.use('/api/notes',require('./routes/notes'));

  app.listen(process.env.PORT  , () => {
  console.log(`my-notebook backend listening at https://my-notebook-mohit.herokuapp.com:${process.env.PORT }`)
})

start();

You also have to await the Promise from mongoose.connect too

const mongoose = require("mongoose");
//const mongoURI = "mongodb://localhost:27017/? readPreference=primary&appname=MongoDB%20Compass&ssl=false";
const mongoURI = "mongodb+srv://mohit_maroliya:Zker42FNU.buD_E@cluster0.n03hm.mongodb.net/myFirstDatabase?retryWrites=true&w=majority"

const connectToMongo = async () => {
  await mongoose.connect(mongoURI, {useNewUrlParser: true}, ()=> {
    console.log("Connected to Mongo Successfully!");
  })
}

module.exports = connectToMongo;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM