【问题标题】:Cannot read properties of undefined (reading 'findOne') with React App deployed on Heroku无法使用部署在 Heroku 上的 React App 读取未定义的属性(读取“findOne”)
【发布时间】:2022-01-27 14:54:15
【问题描述】:

我在部署应用程序(Heroku 上的后端和 Netlify 上的前端)后遇到了问题。之前在 localhost 中运行良好

问题

当我从前端发出 API 请求(登录或 SIgnUP)时,它显示错误。

Cannot read properties of undefined (reading 'findOne')

据说 Heroku 日志是Connected to Mongo Successfully,但我仍然在那儿收到此错误。

我猜的

我已经像这样在 MMongoAtlas 上创建了一个远程 MongoDB 云,

我已经像这样在我的db.js 中连接了它

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;

所以我认为我的 Mongo 连接已连接但未连接到此数据库。

同样在 Google 控制台中,它显示 Unexpected token i in JSON at position 0

代码

我正在分享所涉及文件的代码

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;

模型(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(前端)

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 日志

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')

请帮助我,因为我已经为此苦苦挣扎了很长时间。

【问题讨论】:

    标签: javascript node.js reactjs mongodb heroku


    【解决方案1】:

    在mongodb的网站上,这是连接数据库的方式。

     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);
    

    这是参考链接

    here

    【讨论】:

    • 我正在使用这个 ``` const connectToMongo = async() => { try { await mongoose.connect(mongoURI, {useNewUrlParser: true}, ()=> { console.log("Connected成功到 Mongo!")​​; }) } catch (e) { console.error(e); } } ``` 但得到Operation "users.findOne()" buffering timed out after 10000ms
    【解决方案2】:

    问题在于需求/导出

    您可以更改:

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

    到:

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

    或者你可以像这样导出用户:

    module.exports.User = User;

    代替:

    module.exports = User;

    编辑:超时错误是因为你在猫鼬连接之前监听应用程序所以

    更改db.js 以返回承诺:

    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 = mongoose.connect(mongoURI, {useNewUrlParser: true})
    
    module.exports = connectToMongo;
    

    然后在 index.js 将 app.listen 放入 connectToMongo

    const connectToMongo = require('./db');
    const express = require('express');
    
    
    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'));
    
    connectToMongo().then(() => {
        app.listen(process.env.PORT, () => {
            console.log(`my-notebook backend listening at https://my-notebook-mohit.herokuapp.com:${process.env.PORT}`)
        })
    
    }).catch(error => {
      // handle error here
    })
    

    【讨论】:

    • 我改为module.exports.User = User,但现在显示的是Operation "users.findOne()" buffering timed out after 10000ms
    • 这通常发生在您未连接到数据库时,您在哪里需要 db.js?尝试将其添加到您的 auth.js 文件中
    • 我的 db.js 函数导出到 index.js,然后从 index.js 导出到 auth.js 的路由。我正在添加有问题的 index.js 的代码。
    • 我更新了答案,看看能不能解决你的问题
    • 您对 db.js 的更改导致错误 TypeError: connectToMongo is not a function
    【解决方案3】:

    我认为您的应用程序设置初始化在竞态条件下存在一些问题。你有没有试过像下面这样包装你的初始化。

    index.js

    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();
    

    db.js

    你也必须等待来自 mongoose.connect 的承诺

    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;
    

    【讨论】:

    • 我在 index.js 中做了同样的修改,并在 db.js 中添加了 await,但仍然显示 buffering 的相同错误
    猜你喜欢
    • 2017-01-16
    • 2020-11-02
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    • 2023-01-17
    • 2021-09-06
    相关资源
    最近更新 更多