I'm learning react and node js and I'm making a macro calculator website and basically I get data (calories, macro ratio, etc..) from the user on client side then using those data I make a get request to edamam API server to get (foodID, uri, unit) and post those data again to get macros for each food. Then I calculated data. (It's working fine up to this point on the backend). And I want send this data to back to frontend to display and it's not working here. I'm using axios for the requests. I'm also not too sure it's right way to make API calls. Any help would be appreciated!! Thank you!
Send data to backend from React
async function postData(e){
e.preventDefault();
try{
await axios.post("http://localhost:4000/getData", {formData})
}
catch(error){
console.log(error.response.data);
}
}
Node.js to make API calls and process data
app.post("/getData", (req, res) =>{
// data from React
const targetKcal = req.body.formData.calories;
const proteinRatio = req.body.formData.proteinRatio;
const fatRatio = req.body.formData.fatRatio;
const carbRatio = req.body.formData.carbRatio;
const proteinSource = req.body.formData.proteinSource;
const fatSource = req.body.formData.fatSource;
const carbSource = req.body.formData.carbSource;
const getURL = "https://api.edamam.com/api/food-database/v2/parser?";
const postURL = "https://api.edamam.com/api/food-database/v2/nutrients?";
//GET Request to parse and get uri and foodID to post
try{
Promise.all([
axios.get(getURL, {params :{"ingr" : proteinSource}}),
axios.get(getURL, {params :{"ingr" : fatSource}}),
axios.get(getURL, {params :{"ingr" : carbSource}}),
]).then(axios.spread((proteinData, fatData, carbData) => {
try{
//post data to get macro info for each macros
Promise.all([
axios.post(postURL, {"ingredients" :[{"quantity":1, "measureURI": proteinData.data.hints[0].measures.filter(obj => obj["label"] === "Gram")[0].uri,"foodId":proteinData.data.parsed[0].food.foodId}]}),
axios.post(postURL, {"ingredients" :[{"quantity":1, "measureURI": fatData.data.hints[0].measures.filter(obj => obj["label"] === "Gram")[0].uri,"foodId":fatData.data.parsed[0].food.foodId}]}),
axios.post(postURL, {"ingredients" :[{"quantity":1, "measureURI": carbData.data.hints[0].measures.filter(obj => obj["label"] === "Gram")[0].uri,"foodId":carbData.data.parsed[0].food.foodId}]})
]).then(axios.spread((data1, data2, data3) => {
let proteinKcal = data1.data.totalNutrients.ENERC_KCAL.quantity;
let protein = data1.data.totalNutrients.PROCNT.quantity;
let proteinFat = data1.data.totalNutrients.FAT.quantity;
let proteinCarb = data1.data.totalNutrients.CHOCDF.quantity;
let fatKcal = data2.data.totalNutrients.ENERC_KCAL.quantity;
let fatProtein = data2.data.totalNutrients.PROCNT.quantity;
let fat = data2.data.totalNutrients.FAT.quantity;
let fatCarb = data2.data.totalNutrients.CHOCDF.quantity;
let carbKcal = data3.data.totalNutrients.ENERC_KCAL.quantity;
let carbProtein = data3.data.totalNutrients.PROCNT.quantity;
let carbFat = data3.data.totalNutrients.FAT.quantity;
let carb = data3.data.totalNutrients.CHOCDF.quantity;
//Calculate each macros for target calories
const proteinTargetGram = (targetKcal * (proteinRatio / 100))/proteinKcal;
const fatTargetGram = (targetKcal * (fatRatio / 100))/fatKcal;
const carbTargetGram = (targetKcal * (carbRatio / 100))/carbKcal;
proteinKcal *= proteinTargetGram;
protein *= proteinTargetGram;
proteinFat *= proteinTargetGram;
proteinCarb *= proteinTargetGram;
fatKcal *= fatTargetGram;
fatProtein *= proteinTargetGram;
fat *= fatTargetGram;
fatCarb *= proteinTargetGram;
carbKcal *=carbTargetGram;
carbProtein *= proteinTargetGram;
carbFat *= proteinTargetGram;
carb *= carbTargetGram;
const totalKcal = (proteinKcal fatKcal carbKcal).toFixed(0);
const totalProtein = (protein fatProtein carbProtein).toFixed(0);
const totalFat = (proteinFat fat carbFat).toFixed(0);
const totalCarb = (proteinCarb fatCarb carb).toFixed(0);
const data = {
"totalKcal": totalKcal,
"totalProtein": totalProtein,
"totalFat": totalFat,
"totalCarb": totalCarb,
"proteinTargetGram": proteinTargetGram,
"fatTargetGram": fatTargetGram,
"carbTargetGram":carbTargetGram
};
//send back the data
res.json(data);
}))
}catch(err) { console.log(err); }
}));
}
catch (err) { console.error(err); }
});
Use the data to display on React
function Result() {
const [data, setData] = useState([]);
useEffect(()=>{
const getData = async ()=> {
const response = await axios.get('/getData');
setData(response.data);
};
getData();
});
return (
<div>
<h1>{data.map(item => item)}</h1>
</div>
)
}
export default Result
Error message
-----------------------Edit-------------------------------------------
Instead of res.json(data) I added below
axios.post('/getData', data)
.then(res => console.log(res.json))
.catch(err => console.log(err.json));
display on react
function Result() {
const [data, setData] = useState([]);
useEffect(()=>{
const getData = async ()=> {
const response = await axios.get('http://localhost:4000/getData');
setData(response.data);
};
getData();
});
return (
<div>
<h1>{Object.keys(data).map(key => data[key])}</h1>
</div>
)
}
I still get an error
CodePudding user response:
Your error is generated because you are asking to a GET method that doesn't exist on backend, that's why you see 404 there. You actually have a POST declared (getData), you should request to the POST method by passing the values on the body. something like this:
axios.post('/getData', {
// pass the formData here
formData:{
// calories: ...,
// ...
}
})
.then(function (response) {
// update state
})
.catch(function (error) {
// handle error
});
Axios is fine, if you don't want to use an external package you can use fetch. You can find the documentation here.
For the render: you have to do something different, since you are receiving an object you should map on keys, change this:
<h1>{data.map(item => item)}</h1>
to something like this:
<h1>{Object.keys(data).map(key => key ": " data[key])}</h1>