Reputation: 842
I am printing array of menu items, each has input field type number with quantity to enter for each menu item. I'm using map function to print put all items, within is the form for each item. The only problem is when I am trying to retrieve the input value of item, the first time is taking the empty object of the useState hook that is setting the value of each item. I don't want that but only, when the value is changed. Beside that when I am clicking on arrows up and down the value of input filed is not increasing. Can somebody help?
Here is my code of Meals.js:
import {useState, useEffect, useContext} from 'react';
import CartContext from "./store/CartContext";
const Meals = () => {
const [meals, setMeals] = useState([]);
const [meal, setMeal] = useState({});
const cartCtx = useContext(CartContext);
const fetchMeals = () => {
fetch('https://food-order-7d9f9-default-rtdb.firebaseio.com/meals.json')
.then(response => response.json() )
.then(data => {
const loadedMeals = [];
for(let key in data){
loadedMeals.push({
id: key,
meal: data[key].name,
description: data[key].description,
price: data[key].price,
quantity: 1
})
}
setMeals(loadedMeals);
})
}
useEffect(() => {
fetchMeals();
}, [])
const submitHandler = (e) => {
e.preventDefault();
cartCtx.addItem(meal)
console.log("Iz submitHandler:")
console.log(cartCtx.items)
}
const handleChange = (e, id, inputMeal, description, price) =>{
let updatedMeal = {
id: id,
meal: inputMeal,
description: description,
price: price,
quantity: +e.target.value
}
setMeal(updatedMeal)
console.log("Meal object value");
console.log(meal);
const updatedItemIndex = meals.findIndex(
i => i.id === id
)
const updatedMeals = [
...meals.slice(0, updatedItemIndex),
updatedMeal,
...meals.slice(updatedItemIndex + 1)
]
console.log("From handleChange:");
console.log(updatedMeals)
updatedMeal = {
id: "",
meal: "",
description: "",
price: "",
quantity: ""
}
}
return(
<>
{
meals.map(meal => {
return(
<div key={meal.id}>
<div>
<div>{meal.meal}</div>
<div>{meal.description}</div>
<div>{meal.price}€</div>
</div>
<div className="form-wrapper">
<form onSubmit={ e=> submitHandler(e, meal.id, meal.meal, meal.description, meal.price)}>
<input
label="Amount"
name={`${meal.id}`}
min="1"
max="5"
type="number"
value={meal.quantity}
onChange={e => handleChange(e, meal.id, meal.meal, meal.description, meal.price)}
/>
<button>+ Add</button>
</form>
</div>
</div>
)
}
)
}
</>
)
}
export default Meals;
and my demo uploaded on codesandbox.io:
https://codesandbox.io/s/wonderful-williamson-puptl?file=/src/store/CartProvider.js
Upvotes: 0
Views: 135
Reputation: 1763
Your handleChange
function is wrong, On click of up and down arrow, just get the item that is being updated and update its count
property.
I also updated the submitHandler
.
Here is the updated Code- I hope it solves your problem .
import { useState, useEffect, useContext } from "react";
import CartContext from "./store/CartContext";
const Meals = () => {
const [meals, setMeals] = useState([]);
const cartCtx = useContext(CartContext);
const fetchMeals = () => {
fetch("https://food-order-7d9f9-default-rtdb.firebaseio.com/meals.json")
.then((response) => response.json())
.then((data) => {
const loadedMeals = [];
for (let key in data) {
loadedMeals.push({
id: key,
meal: data[key].name,
description: data[key].description,
price: data[key].price,
quantity: 1
});
}
setMeals(loadedMeals);
});
};
useEffect(() => {
fetchMeals();
}, []);
const submitHandler = (e, mealId) => {
e.preventDefault();
const updatedItemIndex = meals.findIndex((i) => i.id === mealId);
const meal = meals[updatedItemIndex];
console.log(cartCtx.items);
cartCtx.addItem({ ...meal });
};
const handleChange = (e, id, inputMeal, description, price) => {
let updatedMeal = {
id: id,
meal: inputMeal,
description: description,
price: price,
quantity: +e.target.value
};
const updatedItemIndex = meals.findIndex((i) => i.id === id);
const newMeals = [...meals];
newMeals[updatedItemIndex] = updatedMeal;
setMeals(newMeals);
};
return (
<>
{meals.map((meal) => {
return (
<div key={meal.id}>
<div>
<div>{meal.meal}</div>
<div>{meal.description}</div>
<div>{meal.price}€</div>
</div>
<div className="form-wrapper">
<form
onSubmit={(e) =>
submitHandler(
e,
meal.id,
meal.meal,
meal.description,
meal.price
)
}
>
<input
label="Amount"
name={`${meal.id}`}
min="1"
max="5"
type="number"
value={meal.quantity}
onChange={(e) =>
handleChange(
e,
meal.id,
meal.meal,
meal.description,
meal.price
)
}
/>
<button>+ Add</button>
</form>
</div>
</div>
);
})}
</>
);
};
export default Meals;
Upvotes: 1