Reputation: 65
I'm making a program to make a grocery list. I have a list of possible options in a database on MongoDB, and use it to dynamically fill a table. I want to be able to then use a button to push the food name and quantity to a different collection that will be the list of current groceries I need. I'm having trouble changing the quantity of one item without it happening to every row. Here are snippets of my code:
const [list, setList] = useState([])
const [food, setFood] = useState('')
const [quantity, setQuantity] = useState(
new Array(list.length).fill(1)
)
useEffect(() => {
fetch('/api/foods', {
method: 'GET'
})
.then((response) => response.json())
.then((data) => setList(data))
}, [])
This part fetches the list of all foods.
<tbody>
{list.map((item, i) => {
return (
<tr className="itemRow" key={`foodItem-${i}`}>
<td className="foodName">
{item.food}
</td>
<td className="foodQuantity">
<input type="number" id="quantity" value={quantity[i]} onChange={((e) => setQuantity(e.target.value))} />
</td>
<td className="btn">
<button type="button" onClick={((e) => {
e.preventDefault()
setFood(item.food)
fetch('/api/list', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({grocery: food, quantity: quantity.value })
})})}>
Add</button>
</td>
</tr>
)})
}
</tbody>
This is where my rows are generated. My 2 problems are: changing the quantity on one changes it on all, and also my push is not working, they are not actually being added to the database.
Upvotes: 0
Views: 41
Reputation: 11176
I see 2 major issues:
quantity
initialization: at component's first render, list
is an empty array (taht will be filled on fetch return ok but quantity is already initialized). So first of all I would suggest you to initialize quantity after you get values from fetch. Something like:
useEffect(() => {
fetch('/api/foods', {
method: 'GET'
})
.then((response) => response.json())
.then((data) => {
setList(data);
setQuantity(new Array(data.length).fill(1));
})
}, [])
setQuantity(e.target.value)
on input
: as @DBS said, in this way you "overwriting the array with a single value". To solve this, just make another function that takes new value and index of element to update. Something like:
...
const handleQuantity = (value, index) => {
let result = [...list]; //make a copy of list
result[index] = value; //assign new value
setQuantity(result); //update quantity
}
...
<input type="number" id="quantity" value={quantity[i]} onChange={((e) => handleQuantity(e.target.value, i))} />
...
This should solve your problem.
Upvotes: 1