I have an array of objects and I am trying to group the objects by type, like this:
const el = {
Type1: [
{
param1: 1,
param2: value1,
position: 1,
type: 'Type1'
}, {
param1: 2,
param2: value2,
position: 2,
type: 'Type1'
}
],
Type2: [
{
param1: 3,
param2: value3,
position: 1,
type: 'Type2'
}, {
param1: 4,
param2: value4,
position: 2,
type: 'Type2'
}, {
param1: 5,
param2: value5,
position: 3,
type: 'Type2'
}
]
}
The objects in Type property represent choices for radio buttons. This way I set the first choice checked by default:
const groupBy = (array, key) => {
return array.filter(o => o.checked != undefined).reduce((result, currentValue) => {
(result[currentValue[key]] = result[currentValue[key]] || []).push(
currentValue);
return result;
}, {});
};
const [state, setState] = useState({
buttonsTypes: groupBy([...arrayObjects, arrayObjects.map((item, index) => item.position === 1 ? item['checked'] = true : item['checked'] = false)], 'type'),
selections: arrayObjects.filter(item => item.checked)
});
My question is how to map this dynamically and change the checked value on click? I tried this so far:
const selectChoice = (obj) => {
setState(prevState => {
return {
buttonsTypes: ... // Not sure how to update the checked value only for the selection of the specific obj.Type
selections: ...
};
});
};
{Object.entries(state.buttonsTypes).map((item, index) => {
return <React.Fragment>
<div className="some-class"/>
<span id="text">{item[0]}</span>
<div id="radio-button-wrapper">
{item[1].map((choice, index) => {
return <label className="label-css">
<input type="radio" name={choice.param2} value={choice.param1} checked={choice.checked} onClick={() => selectChoice(choice)}/>
</label>
})
}
</div>
</React.Fragment>
})
}
Can anyone suggest some examples or another approach on how to solve this?
Update: As suggested in the answer, I solved it this way by keeping only an array of the selected choices for each radio group:
const selectChoice = (obj) => {
setState(prevState => {
const sel = prevState.selections;
const idx = sel.findIndex(item => item.type === obj.type);
if (idx === -1) {
sel.push(obj);
} else {
sel[idx] = obj;
}
return {
...prevState,
selections: sel
};
});
};
Inside the mapping:
{Object.entries(state.groupedArray).map((item, index) => {
return <React.Fragment>
<div className="some-class"/>
<span id="text">{item[0]}</span>
<div id="radio-button-wrapper">
{item[1].map((choice, index) => {
return <label className="label-css">
<input type="radio" name={choice.param2} value={choice.param1} defaultChecked={choice.position === 1} onClick={() => selectChoice(choice)}/>
</label>
})
}
</div>
</React.Fragment>
})
}
Would appreciate if anyone has any suggestions or comments for improvements.