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],
}
]
});
}
}
You should use a separate variable name for the state instead of value
since the function has a local variable also called value
.
Try like below.
const [values, setVals] = useState({ available: [], done: [] })
function update(field, value) {
const filterIndex = values.done.findIndex((obj) => field === obj.col);
if (filterIndex > -1) {
// get a copy of the previous state done values
const updatedDone = [...values.done];
// update the new value in the copy of the array
updatedDone[filterIndex].val.push(value);
// update the state
setVals((prevValue) => ({ ...prevValue, done: updatedDone }));
} else {
// add the new entry for the new filed with the value
setVals((prevValue) => ({
...prevValue,
done: [
...prevValue.done,
{
col: field,
val: [value],
},
],
}));
}
}
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 value
based on presence/absence of field
in done
.
The method updateStateVal
takes 3 params, the prev-state sv
, the field
& the value
Use ...
spread operator to list down all props of prev (ie, sv
) as-is
Now, override the done
prop
First check if the prev-state's done
already has field
by matching with the col
s from each array-element.
This is done using .map()
in conjunction with .includes()
If found, iterate through the done
array.
For the array element where col
matches field
, .concat
the existing val
array with value
. All other elements go as-is.
If not found, simply .concat
a single-element array ( [{ col: field, val: [value]}]
) to existing done
array.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.