GET http://localhost:3000/api/users/:userId 400 (Bad Request) ? Axios React - node.js

I trying to display data on the client-side of my react application. when sending a get request for single user by id on my server-side I get a 200 ok status and the user information. But when trying to make an axios call on the client-side i get 400 status error. I believe it is how I use req.params in the server-side get request. how can I refactor the GET request so that I can get the response on the client-side.
Controller
router.get("/:userId", (req, res) => {
const { userId } = req.params;
if(!userId){
return res.status(400).json({message: "user id not found"})
}
if(!ObjectId.isValid(userId)){
return res.status(400).json({ message: "userId not valid"})
}
User.findById(userId,(err, user) => {
if(err) {
res.status(500);
console.log("errr 500")
} else {
if(!user)
res.status(400).json({message:"user not found"});
res.status(200).json({"user" : user})
}
})
})
React Component
import React, { Component } from 'react';
import { Link } from 'react-router-dom'
import axios from 'axios'
import PropTypes from "prop-types";
import { connect } from "react-redux";
import Navbar from '../layouts/navbar'
class userDashboard extends Component {
state = {
user: {}
}
getUser = () =>{
const userId = this.props.match.params.id;
axios.get(`http://localhost:5000/api/users/${userId}`).then(res=>{
const user = res.data;
this.setState({
user
})
}).catch((err)=> console.log(err))
}
componentDidMount() {
this.getUser()
}
render() {
const { name } = this.state.user
return (
<div>
<Navbar />
<h1 className="title-text">Hello { name }</h1>
</div>
);
}
}
userDashboard.propTypes = {
// logoutUser: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired,
};
const mapStateToProps = (state) => ({
auth: state.auth,
});
export default connect(mapStateToProps)(userDashboard);
server.js
const express = require("express");
const path = require('path');
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const passport = require("passport");
const cors = require('cors')
const app = express();
const users = require("./controllers/api/users")
app.use(cors());
app.use(
bodyParser.urlencoded({
extended: false
})
);
app.use(bodyParser.json());
app.use(express.static(`${__dirname}/client/build`));
// app.get('/*', (req, res) => {
// res.sendFile(`${__dirname}/client/build/index.html`)
// })
// app.get('/*', (req, res) => {
// res.sendFile(path.join(__dirname, '/../', 'build', 'index.html'));
// });
//DATA BASE CONFIGURATION
const dbkeys = require("./config/key").mongoURI;
mongoose.connect(
dbkeys,
{useNewUrlParser: true} )
.then(()=> console.log("database connection successful"))
.catch(err => console.log(err))
app.use(passport.initialize());
require("./config/passport")(passport);
app.use("/api/users", users);
// app.use("/api", users)
const port = 5000;
app.listen( port, () => console.log("server us up and running on port 5000!"))
Models
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const ClassworkSchema = new Schema({
name: String,
time: Date,
todo: String,
isDone: false
});
const OutcomesSchema = new Schema({
name: String,
time: Date,
todo: String,
isDone: false,
isApproved: false
})
const MeetupSchema = new Schema({
name: String,
time: Date,
location: String,
attended: false
})
const UserSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
},
classwork:{type: [ClassworkSchema], default: []},
outcomes: [OutcomesSchema],
meetups: [MeetupSchema],
});
// const User = mongoose.model('users', UserSchema);
// const Classwork = mongoose.model('Classwork', ClassworkSchema );
// module.exports = {
// User : User ,
// // Classwork : Classwork
// }
module.exports = mongoose.model("users", UserSchema);

try adding "proxy":"http://localhost:5000/" in the package.json in react
then use :
axios.get(`/api/users/${userId}`)...

Related

Status: 500 Internal Server Error While running Post

I want to create an ESN and save it in my database
I'm using Nodejs and Mongodb
you can find the model, route and controller that I have created, what I want is a simple POST API to add an ESN to my data base.
Models
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const esnSchema = new Schema({
esnName: {
type: String,
required: true,
},
esnEmail: {
type: String,
required: true,
},
esnLogo: {
data: Buffer,
contentType: String,
required: false,
}
})
module.exports = mongoose.model("Esn",esnSchema);
Controllers
const Esn = require('../models/esn');
// create new ESN
const createEsn = async (req, res) => {
if (!req.body.esnName) {
res.status(400).send({ message: "Content can not be empty!" });
return;
}
const esn = new Esn({
esnName: req.body.esnName,
esnEmail: req.body.esnEmail,
esnLogo: req.body.esnLogo
});
// Save Esn in the database
esn
.save(esn)
.then(data => {
res.send(data);
})
.catch(err => {
res.status(500).send({
message:
err.message || "Some error occurred while creating the esn"
});
});
};
module.exports = {
createEsn
};
Routes
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const esnSchema = new Schema({
esnName: {
type: String,
required: true,
},
esnEmail: {
type: String,
required: true,
},
esnLogo: {
data: Buffer,
contentType: String,
required: false,
}
})
module.exports = mongoose.model("Esn",esnSchema);
index.js
const express = require('express'),
cors = require('cors'),
swaggerUi = require('swagger-ui-express'),
swaggerDocument = require('./docs/swagger.json');
const Mongo = require('mongodb');
const { default: mongoose } = require('mongoose');
const mainRoutes = require('./routes/esn')
const app = express();
var url = "mongodb://127.0.0.1:27017/";
var databasename = "skills";
Mongo.MongoClient.connect(url).then((client) => {
console.log('Database connected');
const connect = client.db(databasename);
//const collection = connect.createCollection("esn");
console.log('Database: ', connect);
}).catch((err) => {
// Handling the error
console.log(err.Message);
})
app.use(cors());
app.use(express.json());
app.listen(3000, () => {
console.log('Listening on port 3000!');
});
app.get('/', (req, res) => {
res.send('Hello World');
});
app.use('/api/', mainRoutes);
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
I expected to save an esn in the database but I have this error
enter image description here

"message": "Cannot read property 'firstName' of undefined"

I am trying to build a rest API with node express and MongoDB, when I try to test my API with postman I getting this response
"message": "Cannot read property 'firstName' of undefined"
bellow I have attached all my server-side code. first, I have config my application with mongo and started developing the models and respective controllers for that model. inside the controller, I have defined my get and post methods. I don't understand why I am getting that response message when I try to send a post request.
Server Config
import Express from "express";
import Mongoose from "mongoose";
import CorsOptions from "cors";
import bodyParser from "body-parser";
import apiRoutes from "./routes/api.js";
const app = Express();
app.use("/api", apiRoutes);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const CONNECTION_URL =
"mongodb+srv://user:Index-123#cluster0.uhijm.mongodb.net/SustainableIQ?retryWrites=true&w=majority";
const PORT = process.env.PORT || 5000;
Mongoose.connect(CONNECTION_URL)
.then(() =>
app.listen(PORT, () => console.log("server running on port: ${PORT}"))
)
.catch((error) => console.log(error.message));
Routes
import Express from "express";
import {
getApi,
createUser,
adminCreate,
} from "../controller/UserController.js";
const router = Express.Router();
router.get("/", getApi);
router.post("/create", createUser);
router.post("/create-admin", adminCreate);
export default router;
Nodejs Controller
import postUser from "../models/postUser.js";
import adminSchema from "../models/adminUser.js";
export const getApi = async (req, res) => {
try {
postUser
.find()
.exec()
.then((result) => {
if (result) {
res.status(200).json(result);
}
});
} catch (error) {
res.status(404).json({ message: error.message });
}
};
export const adminCreate = async (req, res) => {
try {
const admin = req.body;
const newAdmin = new adminSchema(admin);
newAdmin.firstName = req.body.firstName;
newAdmin.secondName = req.body.secondName;
await newAdmin.save();
res.status(201).json(newAdmin);
} catch (err) {
res.status(409).json({ message: err.message });
}
};
export const createUser = async (req, res) => {
try {
const post = req.body;
const newPost = new postUser(post);
newPost.firstName = req.body.firstName;
newPost.secondName = req.body.secondName;
newPost.position = req.body.position;
newPost.compnayName = req.body.compnayName;
newPost.contactNumber = req.body.contactNumber;
newPost.email = req.body.email;
await newPost.save();
res.status(201).json(newPost);
} catch (err) {
res.status(409).json({ message: err.message });
}
};
mongodb schema
import Mongoose from "mongoose";
var adminSchema = Mongoose.Schema({
firstName: { type: String, required: true },
secondName: { type: String, required: true },
createdAt: {
type: Date,
default: Date.now,
},
});
var adminSchema = Mongoose.model("adminSchema", adminSchema);
export default adminSchema;

GET http://localhost:3000/api/users/:userId 400 (Bad Request), Axios React

I am working on a MERN stack and I am trying to display a single user's data on its own page. The route works on the server-side in Postman, I am able to get the user by Id. But on the client-side I get a 400 bad request when trying to get the user information with axios from that route. could their be a problem with any of my endpoints?
Component
import React, { Component } from 'react';
import { Link } from 'react-router-dom'
import axios from 'axios'
import PropTypes from "prop-types";
import { connect } from "react-redux";
import Navbar from '../layouts/navbar'
// import './userDashboard.css'
class userDashboard extends Component {
state = {
user: {}
}
getUser = () =>{
const userId = this.props.match.params.userId
axios.get('/api/users/' + userId ).then(res=>{
const user = res.data;
this.setState({
user
})
}).catch((err)=> console.log(err))
}
componentDidMount() {
this.getUser()
}
render() {
const { name } = this.state.user
return (
<div>
<Navbar />
<h1 className="title-text">Hello { name }</h1>
</div>
);
}
}
userDashboard.propTypes = {
// logoutUser: PropTypes.func.isRequired,
auth: PropTypes.object.isRequired,
};
const mapStateToProps = (state) => ({
auth: state.auth,
});
export default connect(mapStateToProps)(userDashboard);
controller
router.get("/:userId", (req, res) => {
const { userId } = req.params;
if(!userId){
return res.status(400).json({message: "user id not found"})
}
if(!ObjectId.isValid(userId)){
return res.status(400).json({ message: "userId not valid"})
}
User.findById(userId,(err, user) => {
if(err) {
res.status(500);
console.log("errr 500")
} else {
if(!user)
res.status(400).json({message:"user not found"});
res.status(200).json({"user" : user})
}
})
})
server.js
const express = require("express");
const path = require('path');
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const passport = require("passport");
const app = express();
const users = require("./controllers/api/users")
app.use(
bodyParser.urlencoded({
extended: false
})
);
app.use(bodyParser.json());
app.use(express.static(`${__dirname}/client/build`));
// app.get('/*', (req, res) => {
// res.sendFile(`${__dirname}/client/build/index.html`)
// })
// app.get('/*', (req, res) => {
// res.sendFile(path.join(__dirname, '/../', 'build', 'index.html'));
// });
//DATA BASE CONFIGURATION
const dbkeys = require("./config/key").mongoURI;
mongoose.connect(
dbkeys,
{useNewUrlParser: true} )
.then(()=> console.log("database connection successful"))
.catch(err => console.log(err))
app.use(passport.initialize());
require("./config/passport")(passport);
app.use("/api/users", users);
// app.use("/api", users)
const port = 5000;
app.listen( port, () => console.log("server us up and running on port 5000!"))
Schema
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const ClassworkSchema = new Schema({
name: String,
time: Date,
todo: String,
isDone: false
});
const OutcomesSchema = new Schema({
name: String,
time: Date,
todo: String,
isDone: false,
isApproved: false
})
const MeetupSchema = new Schema({
name: String,
time: Date,
location: String,
attended: false
})
const UserSchema = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
},
classwork:{type: [ClassworkSchema], default: []},
outcomes: [OutcomesSchema],
meetups: [MeetupSchema],
});
// const User = mongoose.model('users', UserSchema);
// const Classwork = mongoose.model('Classwork', ClassworkSchema );
// module.exports = {
// User : User ,
// // Classwork : Classwork
// }
module.exports = mongoose.model("users", UserSchema);
You need to include the server side localhost endpoint in your GET request from the client side.
getUser = () =>{
const userId = this.props.match.params.id;
axios.get(`http://localhost:5000/api/users/${userId}`).then(res=>{
const user = res.data;
this.setState({
user
})
}).catch((err)=> console.log(err))
}
You are requesting a response from the server side , so it is required to include the correct path to which the response should travel.
You will need to include this path in all of the requests you send from the client side to the server side. I recommend using a proxy in the client side package.json as below,
"proxy":"http://localhost:5000"
This will let you write your endpoint path as you have done in your GET request implementation.
For the CORS error,
Install CORS in your server side package.json as npm install cors
Then import CORS to your server.js as const cors = require('cors');
Then use CORS as middleware app.use(cors());

"Cannot overwrite model once compiled" Next.js and Mongoose Schemas

First time using Next.js, I'm trying to implement a Node.js server with MongoDB database, schema models and routes.
I'm not sure what I'm doing wrong, since I tried a lot of combinations, as you can see in the comments in my code. I need to use the models but I'm getting the following error:
"OverwriteModelError: Cannot overwrite termscon model once compiled."
server/models/TermsCon.js:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create Schema
const TermsConSchema = new Schema({
_id: {
type: String,
required: true,
default: "1"
},
text: {
type: String,
required: true,
default: "Lorem Ipsum"
}
});
// const TermsCon = mongoose.model.termscon || mongoose.model('termscon', TermsConSchema);
// module.exports = TermsCon;
// module.exports = mongoose.model('termscon', TermsConSchema);
// export default mongoose.model.TermsCon || mongoose.model('termscon', TermsConSchema)
module.exports = TermsCon = mongoose.model('termscon', TermsConSchema);
server/routes/api/termscons.js:
const express = require('express')
const mongoose = require('mongoose');
const router = express.Router()
const TermsCon = require('../../models/TermsCon')
// const TermsCon = mongoose.model('termscon')
router.get('/', (req, res) => {
TermsCon.find()
.then(tc => {
res.json(tc)
})
});
module.exports = router;
server/index.js:
const express = require('express')
const next = require('next')
const mongoose = require('mongoose')
const port = process.env.PORT || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
mongoose
.connect(process.env.MONGODB_URI,
{
useNewUrlParser: true,
useUnifiedTopology: true,
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
}
)
.then(() => console.log('MongoDB Connected...'))
.catch(err => console.log(err));
const server = express()
server.use("/api/termscons", require("./routes/api/termscons"))
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(port, (err) => {
if (err) throw err
console.log(`Server started on port ${port}`)
})
})
pages/index.js:
import axios from 'axios'
import { useState, useEffect } from 'react'
export default function Home() {
const [ tc, setTc ] = useState()
useEffect(() => {
axios.get('/api/termscons')
.then(res => {
setTc(res.data)
})
.catch(err =>console.log("ERR: ", err))
}, [])
return (
<div>
{tc ?
<p>{tc}</p>
: null}
</div>
)
}
Is it something wrong with the way I'm exporting my schema? With the way I'm connecting to my MongoDB? The routes? Pages?
Any idea will be much appreciated! Thanks!
So I changed the structure:
I gave up creating a custom server since it didn't helped me at all in my Next.js app.
So I don't have any server/index.js anymore or server/routes/api. Actually, there is no "server" folder at all. I simply created a mongodb connection separatelly to help me connect to my database, wich I call at each server api call, like so:
utils/dbConnect.js:
import mongoose from 'mongoose'
async function dbConnect() {
await mongoose.connect(process.env.MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
})
}
export default dbConnect
Since I don't have a custom server anymore, I don't have server/routes/api either. So for the api routes I use the default next.js api folder:
pages/api/termscons.js:
import dbConnect from '../../../utils/dbConnect'
import TermsCon from '../../../models/TermsCon'
export default async function handler(req, res) {
await dbConnect()
switch (req.method) {
case 'GET':
try {
const tc = await TermsCon.find()
res.status(200).json(tc)
} catch (error) {
res.status(400).json({ itemnotfound: "No item found" })
}
break
default:
res.status(400).json({ itemnotfound: "No item found" })
break
}
}
To conclude, I have a folder with all my models in my app main folder:
models/TermsCon.js:
import mongoose from 'mongoose'
const TermsConSchema = new mongoose.Schema({
_id: {
type: String,
required: true,
default: "1"
},
text: {
type: String,
required: true,
default: "Lorem Ipsum"
}
});
export default mongoose.models.TermsCon || mongoose.model('termscon', TermsConSchema);

How to fix post method error using ExpressJs and MongoDB

I'm new in Express.js,MongoDb and mongoose, I have created HTTP request methods, but when running the Post method, nothing is done (nothing saved in the database), and postman still loading and it stops only when I cancel. I want to know what's wrong in my code, thank you .
router.post("/v1/department", async (req, res) => {
try {
const request = req.body
const department = new Department(request)
await department.save()
res.status(200).send(department)
} catch (error) {
res.status(500).send(error)
}
});
This is my model
const mongoose = require("mongoose");
const validator = require('validator')
const Department = mongoose.model('Department', {
name: {
type: String,
required: true,
}
,
email: {
type: String,
required: true,
trim: true,//
lowercase: true,
validate(value) {
if (!validator.isEmail(value)) {
throw new Error('Invalid email!')
}
}
}
,
createdBy: {
type: String,
default: 'SYS_ADMIN'
}
,
updatedBy: {
type: String,
default: 'SYS_ADMIN'
}
,
createdAt: {
type: Date
// ,
// default: Date.getDate()
}
,
updatedAt: {
type: Date
// ,
// default: Date.getDate()
},
isDeleted: {
type: Boolean,
default: false
}
})
module.exports = Department
This is the Index.js
const express = require("express");
const app = express()
const departmentRouter = require("../src/routes/department")
app.use(express.json())
app.use(departmentRouter)
//app.use('/', require('./routes/department'))
const port = process.env.PORT || 5000;//local machine port 3000
app.listen(port, () => (`Server running on local machine port ${port} 🔥`));
The connection to the database is :
const mongoose = require("mongoose");
//Connect to the local mongoDB database for testing the API localy
mongoose.connect('mongodb://127.0.0.1:27017/openemp-api-department', {
useNewUrlParser: true,
useCreateIndex: true
})
You're missing a few things here. Mongoose is never set up in the index.js so there is no connection to the database. This should help you follow step by step
Also in your router you're sending department1 which is never assigned.
If the link doesn't work or you need more information let me know.
For the latest version of Express which is (Express v4.16.0 and higher)
Use this in your server.js file: ----->
const express = require('express');
app.use(express.json());
app.use(express.urlencoded({
extended: true
}));
// For Express version less than 4.16.0
// ------------------------------------
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
otherwise your post request will give you error(like not recognizing any names etc)
so make sure to use these according to to express version
index.js file
const mongoose = require("mongoose");
const express = require("express");
const router = express.Router();
const axios = require("axios");
mongoose.connect(
"YourMongoUri",
{
useNewUrlParser: true,
useUnifiedTopology: true,
}
);
const dataSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
age: {
type: Number,
required: true,
},
});
const modelData = mongoose.model("modelData", dataSchema);
router.get("/", (req, res) => {
modelData.find((err, doc) => {
if (err) console.log(err.message);
else {
res.send(doc);
}
});
});
router.post("/", (req, res) => {
const user = new modelData({
name: req.body.name,
age: req.body.age,
});
user.save((err, doc) => {
if (err) return console.log(err);
res.send(doc);
});
});
router.put("/:id", (req, res) => {
const user = modelData.findByIdAndUpdate(
req.params.id,
{
name: req.body.name,
age: req.body.age,
},
(err, doc) => {
if (err) return console.log(err);
res.send(doc);
}
);
});
router.delete("/:id", (req, res) => {
modelData.findByIdAndDelete(req.params.id, (err, doc) => {
if (err) return console.log(err);
res.send(doc);
});
});
module.exports = router;
server.js file
const express = require("express");
const myRouter = require("./index");
const app = express();
const port = 3000;
app.use(express.json());
app.use(
express.urlencoded({
extended: true,
})
);
s;
app.use("/myroute", myRouter);
app.listen(port, console.log("listening on port 3000"));

Resources