React how can you pass a variable to a get request - javascript

I'm trying to query from a table where the teacherId is equal to the teacherId of the person that logs in but I can't pass that teacherId from the front-end to the back-end.
This is the back end
app.get("/api/get", async(req,res) => {
const teacherId = req.body.teacherId
connection.query(
"SELECT class FROM homework WHERE teacherID = ?",
[teacherId],
(err, result) => {
if (result){
res.send({ message: result })
} else{
console.log(err)
}
}
)
})
This is the front end
useEffect(() => {
Axios.get("http://localhost:1337/api/get", {
teacherId: teacherId
}).then((response) => {
if(response){
setDisplayHomework(response.data.message)
} else{
console.log("error")
}
})
})
const teacherId = localStorage.getItem("teacherId")
I think the problem lies where it says teacherId: teacherId but I don't know why.

You need to use
Axios.get("http://localhost:1337/api/get", {
params: { teacherId }
});
and use req.query.teacherId to read it
If you see the Axios.get signature it is
axios.get(url[, config])
in contrast to
axios.post(url[, data[, config]])
which passes the data as the second argument.
That is because the body in GET requests is not used by the servers. Read HTTP GET with request body for more on this.

Usually you do not send a body with a get request. Put the teacher id into the url. Then this is called path variable.
app.use('/teacher/:teacherId', function(req, res, next) {
console.log(req.params.teacherId);
next();
})

Get requests don't have request bodies unlike post requests, as such the Axios.get function shouldn't have a second parameter for the body. Instead pass your parameters as a url, like this:
useEffect(() => {
Axios.get("http://localhost:1337/api/get?teacherId="+teacherId).then((response) => {
if(response){
setDisplayHomework(response.data.message)
} else{
console.log("error")
}
})
})
Then in your backend code use req.params to access the get request url parameters:
app.get("/api/get", async(req,res) => {
const teacherId = req.params.teacherId
connection.query(
"SELECT class FROM homework WHERE teacherID = ?",
[teacherId],
(err, result) => {
if (result){
res.send({ message: result })
} else{
console.log(err)
}
}
)
})

Related

500 - internal server error my API is not working

I make a crud with products
I send an http request to the /api/deleteProduct route with the product id to retrieve it on the server side and delete the product by its id
To create a product it works only the delete does not work
pages/newProduct.js :
useEffect(() => {
async function fetchData() {
const res = await axios.get('/api/products');
setProducts(res.data);
}
fetchData();
}, []);
const handleSubmit = async (event) => {
event.preventDefault();
const formData = new FormData();
formData.append('picture', picture);
formData.append('name', name);
formData.append('price', price);
formData.append('category', category);
formData.append('description', description);
try {
const res = await axios.post('/api/createProduct', formData);
console.log(res.data);
} catch (error) {
console.log(error);
}
};
const handleDelete = async (id) => {
try {
await axios.delete(`/api/deleteProduct?id=${id}`);
setProducts(products.filter(product => product._id !== id));
} catch (error) {
console.log(error);
}
};
api/deleteProduct.js :
import Product from '../../models/Products';
import { initMongoose } from '../../lib/mongoose';
initMongoose();
export const handleDelete = async (req, res) => {
if (req.method === 'DELETE'){
try {
const { id } = req.params
const product = await Product.findByIdAndRemove(id);
if (!product) {
return res.status(404).json({ message: 'Product not found' });
}
return res.status(200).json({ message: 'Product deleted successfully' });
} catch (error) {
console.log(error);
return res.status(500).json({ message: 'Database error' });
}
}};
I have a 500 error but no error in the server side console and the console.log is not showing like the file was not read
Based on the code you've shared, it seems that the problem may be with the way that the delete request is being handled on the frontend. Specifically, in this line:
await axios.delete("/api/deleteProduct", { params: { id } });
The delete request is supposed to receive the id of the product that should be deleted as a query parameter, but it is being passed as a request body.
Instead of passing it as a parameter, you should pass it as a query parameter by changing it to
await axios.delete(`/api/deleteProduct?id=${id}`);
Also, in your api/deleteProduct.js, you should change the following line:
const { id } = req.query;
to
const { id } = req.params;
Also, you should make sure that the server is running and that the api endpoint '/api/deleteProduct' is accessible and handling the request correctly.
For the last, make sure that the product model is imported and initialized correctly and the database connection is established.
Hope that it solves your problem or, at least, helps :))
I succeeded, I put this (server side):
const { id } = req. query;
and (client side):
await axios.delete(/api/deleteProduct?id=${id});
and I exported my function like this:
export default async function handleDelete(req, res) {

Separating Mongoose code from Express Router

So basically, I'm trying to separate my code that handles data (mongoose) from my express Router code, since I might want to use it elsewhere too.
The first thing I did was, I got rid of the res.json() calls, since I don't want the code to only work returning a http response. I want it to return data, so I can then return that data from my router as a http response, but still use it as regular data elsewhere.
Here is a function I wrote to get data from mongoose.
module.exports.user_login = data => {
console.log(data);
ModelUser.findOne({email: data.email}).then(user => {
if(!user){
console.log({email: 'E-mail address not found'});
return {
status: response_code.HTTP_404,
response: {email: 'E-mail address not found'}
}
}
bcrypt.compare(data.password, user.password).then(isMatch => {
if(!isMatch){
console.log({password: 'Invalid password'});
return {
status: response_code.HTTP_400,
response: {password: 'Invalid password'}
}
}
const payload = {
id: user.id,
email: user.email
};
jwt.sign(
payload,
config.PASSPORT_SECRET,
{
expiresIn: "1h"
},
(err, token) => {
console.log({
status: response_code.HTTP_200,
response: {
success: true,
token: token
}
});
return {
status: response_code.HTTP_200,
response: {
success: true,
token: token
}
}
}
);
});
});
};
When this code gets executed in my route like so:
router.post("/login", (req, res) => {
const { errors, isValid } = validateLogin(req.body);
if(!isValid) return res.status(400).json(errors);
console.log("ret", dm_user.user_login(req.body));
});
The log says the return value of user_login() is undefined, even though right before the return statement in user_login() I am logging the exact same values and they are getting logged.
Before I changed it to a log, I tried to store the return value in a variable, but obviously that remained undefined as well, and I got the error: 'Cannot read propery 'status' of undefined' when trying to use the value.
I am definitely missing something..
Well you have an small callback hell here. It might be a good idea to go with async / await and splitting up your code into smaller chunks instead of putting everyhing in 1 file.
I rewrote your user_login function:
const { generateToken } = require("./token.js");
module.exports.user_login = async data => {
let user = await ModelUser.findOne({ email: data.email });
if (!user) {
console.log({ email: "E-mail address not found" });
return {
status: response_code.HTTP_404,
response: { email: "E-mail address not found" }
};
}
let isMatch = await bcrypt.compare(data.password, user.password);
if (!isMatch) {
console.log({ password: "Invalid password" });
return {
status: response_code.HTTP_400,
response: { password: "Invalid password" }
};
}
const payload = {
id: user.id,
email: user.email
};
let response = await generateToken(
payload,
config.PASSPORT_SECRET,
response_code
);
return response;
};
I have moved your token signing method into another file and promisfied it:
module.exports.generateToken = (payload, secret, response_code) => {
return new Promise((res, rej) => {
jwt.sign(
payload,
secret,
{
expiresIn: "1h"
},
(err, token) => {
if (err) {
rej(err);
}
res({
status: response_code.HTTP_200,
response: {
success: true,
token: token
}
});
}
);
});
};
Now you need to change your router function into an async:
router.post("/login", async (req, res) => {
const { errors, isValid } = validateLogin(req.body);
if(!isValid) return res.status(400).json(errors);
let result = await dm_user.user_login(req.body);
console.log(result);
});
In addition: You get undefined because you return your value to an callback function
I also would seperate your routes from your controllers instead of writing your code inside an anonymous function
Please notice that whenever you are trying to return any value you are always present in the callback function and that is definitely not going to return any value to its intended place.
There are a couple of things you can improve about your code :
1.Donot use jwt inside your code where you are making database calls, instead move it where your routes are defined or make a separate file.
2.If you are intending to re-use the code, I would suggest you either use async-await as shown in the answer above by Ifaruki or you can use something like async.js. But the above shown approach is better.
Also always use 'error' field when you are making db calls like this:
ModelUser.findOne({email: data.email}).then((error,user) => {

Res value is null in an app.get call done from vue.js front-end to express back-end

I am calling this code from the front-end and confirmed that there is a proper db connection and that the Id value is properly passed, and that there is a corresponding value in the database, but for some reason, res is null. What am I missing?
app.get("/api/walletlogin/user/:userId", (req, res) => {
id = req.params.userId
var query = {_id: id}
db.collection("Users").findOne(query, (err, result) => {
if (result) {
console.log(result.userName)
} else {
console.log('No User')
}
})
Here is the front-end call:
axios.get('/api/walletlogin/user/' + accounts)
.then((response) => {
console.log('Logged in With ' + accounts)
router.push('/account')
})
.catch((errors) => {
console.log('Cannot log in')
})
}).catch((err) => {
console.log(err, 'err!!')
})
You could try to convert your id to an objectID.
var ObjectId = require('mongodb').ObjectId;
var id = ObjectId(req.params.userId);
to search by id, you must use the ObjectID class from the mongodb package. Here is an example invented by me, it does not reflect the real work, but I hope it will become clear on it:
const { ObjectID } = require('mongodb');
const id = '5ee4f69bfa0b960de8aec158'; // in your example is req.params.userId
db.collection('users').findOne({ _id: new ObjectID(id)}, (error, result) => {
if (error) {
throw error;
}
console.log(result);
})
I am adding the details of the issue initially encountered in case someone else would experience it in the future. The value that is passed from the front-end is a cryptocurrency address. For some reason, some of the characters passed were upper-case, while the same address had been stored in the database with these same characters as lower case. Thus, one needs to add code to make sure that the case of the letters found in the respective addresses is ignored.
J

ExpressJS variable undefined

I have an ExpressJS app that when a user makes a POST request to a route, it should lookup the ID in the MongoDB using req.params.formId
I have some console.log statements tfor debugging and so I can see what info is being returned.
The route should lookup the ID passed and when it finds it, use the req.body data and also a field from the MongoDB document but this just seems to return as undefined
Here is the code for the route:
app.post("/api/v1/forms/:formId", (req, res) => {
const { name, email, message } = req.body;
console.log(req.body);
Form.findById(req.params.formId, Form.recipient, err => {
if (err) {
res.send(err);
} else {
const formRecipient = Form.recipient;
const newForm = {
name,
email,
message,
recipient: formRecipient
};
console.log(newForm);
const mailer = new Mailer(newForm, contactFormTemplate(newForm));
try {
mailer.send();
res.send(req.body);
} catch (err) {
res.send(err);
}
}
});
});
So an example, if I make a POST request to localhost:5000/api/v1/forms/5ad90544883a6e34ec738c19 the console.log of newForm shows { name: ' Mr Tester',
email: 'person#example.com',
message: 'Hi there',
recipient: undefined }
The forms Mongoose schema has a field named recipient
the correct way is to provide the fields you want to get as the second argument:
Form.findById(req.params.formId, 'recipient', (err, form) => {
if (err) {
// error handling code
} else {
const formRecipient = form.recipient;
}
...
});
here's the Docs

Mongoose method findbyIdAndRemove is failing when called client-side

I have a route in my app that calls the mongoose method findByIdAndRemove. When I test this route in postman, I can successfully delete documents in my database, but when I call this method from my javascript file in the client, I get an error.
I getting a 404 (the response status I dictated if no document can be found). I also get an error in the terminal saying "can't set headers after they are sent." I'm not sure why I'm getting this error. Why is my route working in postman, but not when I call it from the client-side?
How should I get this working?
Here is my route on the server-side:
exports.deleteEmployee = function (req, res, next) {
const id = mongoose.Types.ObjectId(req.body.id);
Employee.findByIdAndRemove(id, (err, employee) => {
if (err) { return next(err); }
// if no employee with the given ID is found throw 400
if (!employee) { res.status(404).json('No employee with that ID'); }
res.status(200).json(employee);
});
};
Here is where I call this route from the client-side:
export const employeeDelete = ({ id }) => {
const props = { id };
return () => {
axios.delete(`${api.API_ROUTE}/employee/delete`, props)
.then(() => {
// push user back to EmployeeList and reset view stack
Actions.employeeList({ type: 'reset' });
})
.catch(err => {
console.log(err);
});
};
};
You're getting "can't set headers after they are sent." error because you're trying to respond with 200 code after having responded with 400 code.
You should surround the response statements with a if/else statement:
if (!employee) { res.status(404).json('No employee with that ID'); }
else{res.status(200).json(employee);}
It turns out the axios delete method does not take a data object, so when I passed the object called props, it never reached the server. I instead passed id as a url parameter like this:
export const employeeDelete = ({ id }) => {
return () => {
axios.delete(`${api.API_ROUTE}/employee/delete/${id}`)
.then(() => {
// push user back to EmployeeList and reset view stack
Actions.employeeList({ type: 'reset' });
})
.catch(err => {
console.log(err);
});
};
};

Categories