How can I send a input array to backend? - node.js

I am trying to create a form that we can send an array to backend using input with mapping but I ended up created input name different from useState. Like it send seperate data to backend.
Here is my following code in front end:
const initialFormState = {
rules: teamData.rules.map((value) => value),
creator: teamData.User.public_user_id,
};
const [updateTeamData, setUpdateTeamData] = useState(initialFormState);
const handleSubmit = async (event) => {
event.preventDefault();
setEditing(false);
console.log("updateTeamData", updateTeamData);
console.log("input", inputs);
// Send update request
const res = await axios.put(`/api/v1/teams/team/${teamId}`, updateTeamData);
// If no validation errors were found
// Validation errors don't throw errors, it returns an array to display.
if (res.data.validationErrors === undefined) {
// Clear any errors
setErrorsArr([]);
// Hide the errors component
setShowErrors(false);
// Call update profiles on parent
fetchTeamData();
} else {
// Set errors
setErrorsArr(res.data.validationErrors.errors);
// Show the errors component
setShowErrors(true);
}
};
<form onSubmit={handleSubmit}>
{inputs?.map((data, idx) => {
return (
<input
name={teamData.rules[idx]}
onChange={handleChange}
placeholder={`Rule ${idx + 1}`}
defaultValue={teamData.rules[idx]}
/>
);
})}
When I hit submit and the console log gave me this data:
{rules: Array(0), creator: "nh1619917421620", "": "3"}
"": "3"
creator: "nh1619917421620"
rules: []
__proto__: Object
and here is my code from backend:
exports.updateTeamData = async (req, res) => {
// Get userId
const userId = req.session.passport.user.id;
// Get teamId
const publicTeamId = req.params.teamId;
// Fetch private id for team
const teamId = await getTeamId(publicTeamId);
// The user making the request
const userPublicId = req.session.passport.user.publicId;
// The creator of the team
const creatorPublicId = req.body.creator;
// Check who is making the request
if (userPublicId !== creatorPublicId) {
res.status(401).json("msg: You cant update a team you did not create");
}
const picture = req.body.teamAvatar;
const rules = req.body.rules;
const rules = req.body.rules;
console.log("rules", rules);
console.log("body", req.body);
// Updates
const payload = {
rules: rules,
mergedTo: teamId,
};
}
How can I do my form right way?

Related

.post call not returning expected response

I am building out the backend for a flash card app for which you can find the repo here. There is a table called categories. There is an endpoint for adding a category.
router.post("/", protect, createCategory);
The endpoint runs a createCategory function which has logic separated out into a categoryController.js file.
const Categories = require("../models/categoryModel");
const createCategory = async (req, res) => {
const { title } = req.body;
const userId = req.user.id;
if (!title) {
res.status(404).json({ errMsg: "Please provide a title" });
} else {
const category = await Categories.createCategory({ title, userId });
console.log("category: ", category);
res.status(201).json(category);
}
};
The createCategory controller function in turn calls a createCategory function from the categoryModel.js file. The function from the model runs the database operations. Specifically, it inserts a new category into the database and references another function--getCategoryById--to return the newly created category.
const getCategoryById = (id) => {
return db("categories").where({ id }).first();
};
const createCategory = (category) => {
return db("categories")
.insert(category, "id")
.then((ids) => {
const [id] = ids;
return getCategoryById(id);
});
};
The problem is when I make the .post to create a new category, nothing is returned in the response. The database gets updated just fine but nothing is returned. You can see that I put a console.log in the controller and that is coming back undefined. I am not sure why.

I need to make a request using Prisma that brings selected products by IDs

I have a backend function that returns a request based on an id.
I need it to return me based on an array of ids
If I pass only one ID it works fine, but if I pass more than one, it gives error....
Can someone help?
Thanks
Backend function:
` import prisma from '../../../../libs/prisma'
export default async function handle(req, res) {
const { ids } = req.query
const idsArray = ids.split(',')
const products = await prisma.product.findMany({
where: {
id: {
in: Number(idsArray),
},
},
})
res.json(products)
}`
And Frontend function that passes the parameters on the front is:
const { selectProducts, setSelectProducts } = useContext(ProductContext)
const [productsInfo, setProductsInfo] = useState([])
useEffect(() => {
const uniqIds = [...new Set(selectProducts)]
fetch('/api/products/getAllSelectedProducts?ids=' + uniqIds.join(',')).then((response) => response.json()).then((json) => setProductsInfo(json))
}, [selectProducts])

Cannot set headers after they are sent to the client /ErrorCaptureStackTrace(err);

I try to make a request API for a post profile but for some reason the request had fail, I don't understand. So when I try it with the postman, first of all i sent an empty body request it return me the errors expected {"handle": "handle field is required",
"status": "status field is required",
"skills": "skills field is required"} , it work but when I resent the request again for example with just the handle field or two fields or all fields it throw me this kind of error: "Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client" instead of sending me errors or the response. So this is my code :
router.post('/', passport.authenticate('jwt', {session: false}), (req, res) => {
const {isValid, errors} = validateProfileInput(req.body);
// Check infos valid
if(!isValid) {
res.status(400).json(errors);
}
//Get fields
const profileFields = {};
profileFields.user = req.user.id;
if (req.body.handle) profileFields.handle = req.body.handle;
if (req.body.company) profileFields.company = req.body.company;
if (req.body.website) profileFields.website = req.body.website;
if (req.body.location) profileFields.location = req.body.location;
if (req.body.bio) profileFields.bio = req.body.bio;
if (req.body.status) profileFields.status = req.body.status;
if (req.body.githubusername) profileFields.githubusername = req.body.githubusername;
//Skills - Split into array
if (typeof req.body.skills) profileFields.skills = req.body.skills.split(',');
// Social
profileFields.social = {};
if (req.body.youtube) profileFields.social.youtube = req.body.youtube;
if (req.body.facebook) profileFields.social.facebook = req.body.facebook;
if (req.body.linkedin) profileFields.social.linkedin = req.body.linkedin;
if (req.body.instagram) profileFields.social.instagram = req.body.instagram;
Profile.findOne({user: req.user.id}).then(profile => {
if (profile) {
// Update
Profile.findOneAndUpdate({user: req.user.id}, {$set: profileFields}, {new: true}).then(profile => res.json(profile))
} else {
// Create
// Check if handle exists
Profile.findOne({handle: profileFields.handle}).then(profile => {
if (profile) {
errors.handle = "That's handle already exists!"
res.json(errors)
}
// Create new profile && save
new Profile(profileFields).save()
.then(profile => res.json(profile))
})
}
})
})

How to make a GET Request for a unique register with AXIOS and NodeJS/Express

I'm trying to make GET request to external API (Rick and Morty API). The objective is setting a GET request for unique character, for example "Character with id=3". At the moment my endpoint is:
Routes file:
import CharacterController from '../controllers/character_controller'
const routes = app.Router()
routes.get('/:id', new CharacterController().get)
export default routes
Controller file:
async get (req, res) {
try {
const { id } = req.params
const oneChar = await axios.get(`https://rickandmortyapi.com/api/character/${id}`)
const filteredOneChar = oneChar.data.results.map((item) => {
return {
name: item.name,
status: item.status,
species: item.species,
origin: item.origin.name
}
})
console.log(filteredOneChar)
return super.Success(res, { message: 'Successfully GET Char request response', data: filteredOneChar })
} catch (err) {
console.log(err)
}
}
The purpose of map function is to retrieve only specific Character data fields.
But the code above doesn't work. Please let me know any suggestions, thanks!
First of all I don't know why your controller is a class. Revert that and export your function like so:
const axios = require('axios');
// getCharacter is more descriptive than "get" I would suggest naming
// your functions with more descriptive text
exports.getCharacter = async (req, res) => {
Then in your routes file you can easily import it and attach it to your route handler:
const { getCharacter } = require('../controllers/character_controller');
index.get('/:id', getCharacter);
Your routes imports also seem off, why are you creating a new Router from app? You should be calling:
const express = require('express');
const routes = express.Router();
next go back to your controller. Your logic was all off, if you checked the api you would notice that the character/:id endpoint responds with 1 character so .results doesnt exist. The following will give you what you're looking for.
exports.getCharacter = async (req, res) => {
try {
const { id } = req.params;
const oneChar = await axios.get(
`https://rickandmortyapi.com/api/character/${id}`
);
console.log(oneChar.data);
// return name, status, species, and origin keys from oneChar
const { name, status, species, origin } = oneChar.data;
const filteredData = Object.assign({}, { name, status, species, origin });
res.send(filteredData);
} catch (err) {
return res.status(400).json({ message: err.message });
}
};

Iterate dataArray to create an object is not happening

How can I parse the incoming nomData data array and store those values into an object along with userEmail ? Somehow below code is not working, could someone pleas advise the issue here.
Expected database columns values:
var data = { useremail: userEmail, nomineeemail: email, nomineename: name, nomineeteam: team, reason: reason }
server.js
app.post('/service/nominateperson', async (req, res) => {
try {
const userEmail = req.body.userEmail;
const nomData = req.body.nomRegister;
const formData = {
useremail: userEmail,
nomineeemail: {},
nomineename: {},
nomineeteam: {},
reason: {}
}
const newArray = nomData.map(item => {
formData.nomineeemail = item.email;
formData.nomineename = item.name;
formData.nomineeteam = item.team;
formData.reason = item.reason;
});
var data = { useremail: userEmail, nomineeemail: email, nomineename: name, nomineeteam: team, reason: reason }
// Ideally I should get nomData
//items parsed create an data object and pass that into bulkCreat() method:
const numberOfNominations = await NominationModel.count({where: {useremail: userEmail}});
if (numberOfNominations <= 3) {
const nominationData = await NominationModel.bulkCreate(data);
res.status(200).json({message: "Nomination submitted successfully !"});
} else {
res.status(202).json({message: "Nomination limit exceeded, please try next week !"});
}
} catch (e) {
res.status(500).json({fail: e.message});
}
});
So i assume nomData is an array containing multiple nominations. So if you want to bulkCreate with data you should pass an array instead of an object.
const data = nomData.map(item => ({
useremail: userEmail,
nomineeemail: item.email,
nomineename: item.name,
nomineeteam: item.team,
reason: item.reason
}));
...
await NominationModel.bulkCreate(data)

Resources