I'm having problems setting state for my dynamic checkbox for my array, changing an object from false to true, using a checked handler.
below is my code:
const [form, setForm] = useState({
tags:[
{ name: "Athletic/Higher caloric", isChecked: false },
{ name: "Aggressive Weight Loss", isChecked: false },
{ name: "Quick and Easy", isChecked: false } ]})
const onCheckedHandler = (index) => {
const updatedTags =
form.tags.map((tag, i) => {
if (index === i) {
form.tags[i].isChecked = !form.tags[i].isChecked;
}
return { tag };
});
setForm(updatedTags);
return (
{form.tags.map((tag, i) => (
<div>
<label>{tag.name}</label>
<input
type="checkbox"
checked={tag.isChecked}
onChange={(event) => onCheckedHandler(i)}
key={i} />
</div>
))})
I get this error: "Uncaught TypeError: Cannot read properties of undefined (reading 'map') at Create (line:107)"
But line 107 is just the start of another map function that works and is totally unrelated. What am I doing wrong? I tried avoiding mutating the isChecked value directly in the object with an if statement. Maybe it's how I setState?
CodePudding user response:
It is my understanding that:
- Initial state is an object
const [form, setForm] = useState({...});
- This has a prop named tags.
- But, the variable
updatedTags
(in the handler-method) is an array. It's not an object. - So, setForm(updatedTags) will set
form
to be an array which will not have any prop namedtags
Consequently, please try changing the handler like so:
const onCheckedHandler = (index) => {
setForm(prev => ({
...prev,
tags: [
...prev?.tags?.map(
({isChecked, ...rest}, idx) => (
idx === index
? {...rest, isChecked: !isChecked}
: {...rest, isChecked}
)
)
]
}));
};
Also, please use checks before attempting map on the return
as well. May be try something like so:
form?.tags?.map(...)
OR
form && form.tags && Array.isArray(form.tags) && form.tags.map(...)
CodePudding user response:
The problem comes probably from here:
return (
{form.tags.map((tag, i) => (
<div>
<label>{tag.name}</label>
<input
type="checkbox"
checked={tag.isChecked}
onChange={(event) => onCheckedHandler(i)}
key={i} />
</div>))}
)
The issue is you're trying to render using the form
state which at the time of mounting (of the component) is probably undefined
. As your error says cannot read property of undefined, reading map
it probably refers to that form.tags
is undefined and can't read map of it.
A good idea is to check before rendering if what you're trying to render is defined or not. For example:
return (
{form.tags ? form.tags.map((tag, i) => (
<div>
<label>{tag.name}</label>
<input
type="checkbox"
checked={tag.isChecked}
onChange={(event) => onCheckedHandler(i)}
key={i} />
</div>)) : <div>Loading</div>}
)