'Push into array of objects with nested level using spread operator
I am having an object containing array of objects with following format which is stored in a state
const [value, setVal] = useState({ available : [], done: [] })
done is an array of objects with following structure
[{col: "test", val: ["abc","xyz"]}]
I am writing a function that takes field and value as input parameters. If the field is present in done array, then I need to push it inside its corresponding val array. Else I need to create a new object and then push it inside. How can I achieve this?
How can I set the state in both the cases?Code that I tried is below
function update(field, value){
const filterIndex = value.done.findIndex((obj) => field === obj.col);
if (filterIndex > -1) {
value.done[filterIndex].val.push(value);
} else {
setVal({
...value,
done: [
...value.done,
{
col: field,
val: [value],
}
]
});
}
}
Solution 1:[1]
This may be one possible solution:
Code Snippet
const stateVal = { available : [], done: [{col: "test", val: ["abc","xyz"]}] };
const updateStateVal = (sv, field, value) => ({
...sv,
done: (
sv.done.map(ob => ob.col).includes(field)
? sv.done.map(ob => (
ob.col === field
? {...ob, val: ob.val.concat([value])}
: {...ob}
))
: sv.done.concat([{ col: field, val: [value] }])
)
});
console.log('existing col test: ', updateStateVal(stateVal, 'test', 'def'));
console.log('non-exist col test2: ', updateStateVal(stateVal, 'test2', 'def'));
How to use
setVal(prev => ({...updateStateVal(prev, field, value)}));
Explanation
The objective is to insert
valuebased on presence/absence offieldindone.The method
updateStateValtakes 3 params, the prev-statesv, thefield& thevalueUse
...spread operator to list down all props of prev (ie,sv) as-isNow, override the
donepropFirst check if the prev-state's
donealready hasfieldby matching with thecols from each array-element.This is done using
.map()in conjunction with.includes()If found, iterate through the
donearray.For the array element where
colmatchesfield,.concatthe existingvalarray withvalue. All other elements go as-is.If not found, simply
.concata single-element array ([{ col: field, val: [value]}]) to existingdonearray.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
