使用扩展运算符推入具有嵌套级别的对象数组
Push into array of objects with nested level using spread operator
我有一个包含以下格式的对象数组的对象,该对象存储在一个状态中
const [value, setVal] = useState({ available : [], done: [] })
done
是具有以下结构的对象数组
[{col: "test", val: ["abc","xyz"]}]
我正在编写一个将 field
和 value
作为输入参数的函数。如果该字段存在于 done
数组中,那么我需要将它推入其对应的 val
数组中。否则我需要创建一个新对象,然后将其推入其中。我怎样才能做到这一点?
如何在这两种情况下设置状态?我试过的代码如下
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],
}
]
});
}
}
这可能是一种可能的解决方案:
代码段
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'));
使用方法
setVal(prev => ({...updateStateVal(prev, field, value)}));
说明
objective是在done
的field
的presence/absence的基础上插入value
。
方法updateStateVal
需要3个参数,prev-statesv
,field
和value
使用...
展开运算符列出prev的所有属性(即sv
)as-is
现在,覆盖 done
属性
首先通过与每个 array-element 中的 col
匹配来检查 prev-state 的 done
是否已经有 field
.
这是使用 .map()
结合 .includes()
完成的
如果找到,遍历 done
数组。
对于 col
匹配 field
的数组元素,.concat
现有 val
数组与 value
。所有其他元素变为 as-is.
如果没有找到,只需.concat
一个single-element数组([{ col: field, val: [value]}]
)到现有的done
数组。
您应该为状态使用单独的变量名称而不是 value
,因为该函数有一个局部变量也称为 value
。
像下面这样尝试。
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],
},
],
}));
}
}
我有一个包含以下格式的对象数组的对象,该对象存储在一个状态中
const [value, setVal] = useState({ available : [], done: [] })
done
是具有以下结构的对象数组
[{col: "test", val: ["abc","xyz"]}]
我正在编写一个将 field
和 value
作为输入参数的函数。如果该字段存在于 done
数组中,那么我需要将它推入其对应的 val
数组中。否则我需要创建一个新对象,然后将其推入其中。我怎样才能做到这一点?
如何在这两种情况下设置状态?我试过的代码如下
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],
}
]
});
}
}
这可能是一种可能的解决方案:
代码段
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'));
使用方法
setVal(prev => ({...updateStateVal(prev, field, value)}));
说明
objective是在
done
的field
的presence/absence的基础上插入value
。方法
updateStateVal
需要3个参数,prev-statesv
,field
和value
使用
...
展开运算符列出prev的所有属性(即sv
)as-is现在,覆盖
done
属性首先通过与每个 array-element 中的
col
匹配来检查 prev-state 的done
是否已经有field
.这是使用
完成的.map()
结合.includes()
如果找到,遍历
done
数组。对于
col
匹配field
的数组元素,.concat
现有val
数组与value
。所有其他元素变为 as-is.如果没有找到,只需
.concat
一个single-element数组([{ col: field, val: [value]}]
)到现有的done
数组。
您应该为状态使用单独的变量名称而不是 value
,因为该函数有一个局部变量也称为 value
。
像下面这样尝试。
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],
},
],
}));
}
}