Reputation: 6953
I'm trying to use React Hooks to update the list of items. When users click on the check-box, the app should render the items which have been selected as purchased.
I could log the event of the handPurchase()
and the state is correct, however, I can't make the function render the latest state.
With class, I can do:
const handlePurchase() {
// ...
this.setState(updatedGroceries);
}
this.state.groceries.map(//...render list
This is the code:
export default function CheckboxList() {
let initialGroceries = [
{
id: "one",
text: "Apple",
purchased: false
},
{
id: "two",
text: "Banana",
purchased: false
}
];
const [groceries, setGroceries] = useState(initialGroceries);
const handlePurchase = (id: string) => () => {
groceries.forEach((item) => {
if (item.id === id) {
item.purchased = true;
}
});
setGroceries(groceries);
}
return (
<List>
{groceries.map((item) => {
const labelId = `checkbox-list-label-${item.id}`;
return (
<ListItem key={item.id} role={undefined} dense button onClick={handlePurchase(item.id)}>
<ListItemIcon>
<Checkbox
checked={item.purchased}
inputProps={{ 'aria-labelledby': labelId }}
/>
</ListItemIcon>
<ListItemText id={labelId} primary={item.text} />
</ListItem>
);
})}
</List>
);
}
Also, if I do this:
const updatedGroceries = groceries.forEach((item) => {
if (item.id === id) {
item.purchased = true;
}
});
setGroceries(updatedGroceries);
I get this error:
Argument of type 'void' is not assignable to parameter of type 'SetStateAction<{ id: string; text: string; purchased: boolean; }[]>'. TS2345
Upvotes: 0
Views: 72
Reputation: 15166
The issue is that forEach
does not return anything as you might expect. I guess you would like to update with setGroceries
the purchased
property on the elements where the provided id
is equals to the current one to true
. So you need to return an array for example with Array.prototype.map()
. From the documentation:
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
I guess the following can work for you:
const updatedGroceries = groceries.map((item) => {
if (item.id === id) {
item.purchased = true;
}
return item;
});
setGroceries(updatedGroceries);
In your code you were assigning to updatedGroceries
the forEach
result which is undefined
because it does not return anything, find here in the docs.
I hope that helps!
Upvotes: 2