I'm making an ecommrece project, in search bar I'm displaying checkboxes with categories from the API, all of those have value active == true by default. This is how I'm mapping them:
{categories.map((category) => {
return (
<>
<input type="checkbox" onClick={() => handleCheckbox(category)}
defaultChecked={category.active} key={category.name} />
<label style={{marginLeft:"5px"}} htmlFor={category.name}>{category.name}</label><br/>
</>
)
})}
Then I run this function to change category.active property from true to false, when the exact checkbox is clicked, then I want to update this object using useState
const handleCheckbox = (category) => {
let tempCategory = category
if (tempCategory.active == true) {
tempCategory.active = false;
} else {
tempCategory.active = true;
}
setCategories({...categories, [tempCategory.id]: tempCategory})
console.log(category.active)
}
Unfortunetly when I click on the checkbox I'm getting an error from React:
TypeError: categories.map is not a function
And it points to categories.map, I have no idea how to fix it. All I want is to update specific object in the categories array.
I believe your categories start life as an array of category objects, and you meant to setCategories to an array - but instead you're setting it to an object.
You also need to make sure you dont double up tempCategory. something like this:
setCategories([
...categories.filter(x => x.id != tempCategory.id),
tempCategory
]);
However, this will reorder your categories, putting tempCategory at the end, so another option is to slice the array correctly
const tmpIdx = categories.findIndex(x => x.id == tempCategory.id);
setCategories([
...categories.slice(0,tmpIdx),
tempCategory,
...categories.slice(tmpIdx+1),
]);
Another option is make your categories an object and use Object.values(categories).map(...) but this makes ordering your categories harder, as there is no fixed ordering of object keys/values like there is with an array.