my state looks like this:
const [options, setOptions] = useState({ numbers: false, animals: false, greetings: false, food: false, colors: false, other: true })
and I'm trying to update a single boolean based on a checkbox.
At first I used a switch statement like so:
switch (e.target.id) {
case 'numbers': setOptions((prevState) => ({ ...prevState, numbers: e.target.checked })); break;
case 'animals': setOptions((prevState) => ({ ...prevState, animals: e.target.checked })); break;
case 'greetings': setOptions((prevState) => ({ ...prevState, greetings: e.target.checked })); break;
case 'food': setOptions((prevState) => ({ ...prevState, food: e.target.checked })); break;
case 'colors': setOptions((prevState) => ({ ...prevState, colors: e.target.checked })); break;
case 'other': setOptions((prevState) => ({ ...prevState, other: e.target.checked })); break;
default: break
}
but I think as I add more options, I'll want something cleaner, I was hoping something like
setOptions((prevState) => ({ ...prevState, options[e.target.id]: e.target.checked }))
would work but no luck. I also tried
options[e.target.id] = e.target.checked
but it doesn't do a refresh.
CodePudding user response:
Your cleaner version is definitely the preferred one but the syntax for computed property names is
{
[ key ]: value
}
I'd be inclined to use a name
attribute instead of id
, mainly to avoid accidentally duplicating IDs.
const handleCheckbox = (e) => {
setOptions(prev => ({
...prev,
[e.target.name]: e.target.checked
}));
};
You just need to make sure your checkbox elements have appropriate attributes
{Object.entries(options).map(([option, checked]) => (
<label>
<input
type="checkbox"
name={option}
checked={checked}
onChange={handleCheckbox}
/>
{option}
</label>
))}
CodePudding user response:
Add a name attribute with each checkbox and this name should a valid key from options.
const [options, setOptions] = useState({ numbers: false, animals: false, greetings: false, food: false, colors: false, other: true })
const handleStateChange = (e)=>{
const {name,value} = e.target
setOptions(preState => ({...preState ,[name]:value}))
}
<input type='checkbox' name='numbers' value={options.numbers} onChange={handleStateChange} />
<input type='checkbox' name='animals' value={options.animals} onChange={handleStateChange} />
<input type='checkbox' name='greetings' value={options.greetings} onChange={handleStateChange} />