通过展开操作删除对象键 returns undefined
Remove object key by spread operated returns undefined
我正在创建单选按钮对象。数组中的每个对象都有对象 {value: 1, text: 'Sometext'} 并且如果单选按钮是 selected,添加 selected: true 到对象中并删除 select来自其他人。
const onChoiceChange = function setChoiceStateAndUpdateSelectedObject(e) {
let updating = []
choices.map((item, index) => {
if (item.value == e.target.value) {
updating.push({...item, selected: true})
} else {
item.selected && updating.push({selected, ...item} = item) //here it says selected undefined even with the condition check
!item.selected && updating.push(item)
}
})
setChoices(updating)
console.log('updating', updating)
}
我在这里使用代码片段工具,它可以工作,但是当我在 NextJS 中编译我的代码时,出现以下错误。
我在片段中使用相同的代码,我不明白为什么当我第二次 select 一个不同的单选按钮时它说 selected 未定义。
let choices = [
{ value: 1, text: 'This is value 1' },
{ value: 2, text: 'This is value 2' },
{ value: 3, text: 'This is value 3' },
{ value: 4, text: 'this is value 4'}
]
document.addEventListener('input',(e)=>{
let updating = []
if(e.target.getAttribute('name')=="choices") {
choices.map((item, index) => {
if (item.value == e.target.value) {
updating.push({...item, selected: true})
} else {
item.selected && updating.push({selected, ...item} = item)
!item.selected && updating.push(item)
}
})
}
console.log(updating)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<input type='radio' name='choices' value='1'/>
<input type='radio' name='choices' value='2'/>
<input type='radio' name='choices' value='3'/>
<input type='radio' name='choices' value='4'/>
请将 else 块中的行更新为
item.selected && updating.push(item) //
好的,所以 selected 对于解析器来说是未知的 variable/entity 因为您没有在代码中的任何地方定义。 selected:item.selected
将使 selected:true
.
请在下面找到工作片段:
let choices = [{
value: 1,
text: 'This is value 1'
},
{
value: 2,
text: 'This is value 2'
},
{
value: 3,
text: 'This is value 3'
},
{
value: 4,
text: 'this is value 4'
}
]
document.addEventListener('input', (e) => {
let updating = []
if (e.target.getAttribute('name') == "choices") {
choices.map((item, index) => {
if (item.value == e.target.value) {
updating.push({ ...item,
selected: true
})
} else {
item.selected && updating.push({
selected:item.selected,
...item
} = item)
!item.selected && updating.push(item)
}
})
}
console.log(updating)
})
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
</head>
<body>
<input type='radio' name='choices' value='1' />
<input type='radio' name='choices' value='2' />
<input type='radio' name='choices' value='3' />
<input type='radio' name='choices' value='4' />
</body>
</html>
您正在混淆 rest and spread 语法。两者都是椭圆(...
),但基本上是相反的。
在您的真实情况下,您正在使用传播 {...item, selected: true}
,将 item
中的所有值设置为新对象,然后添加键 selected
(可能覆盖项目中的先前 selected
键)。工作正常。
在你的 else 情况下,你正在使用 rest(并且通过扩展,destructuring,{selected, ...item} = item
。解构(和 rest)仅是 asignment。解构创建新变量,或者,如果用括号括起来,则重新分配旧变量。休息,特别是意味着 "take all of the entries I didn't ask for by name and shove them into a new object called [blank]"。你不是在向数组添加新对象。你正在将 items.selected
的值分配给一个未定义的变量 selected
,并试图将 item
中的其余条目重新分配给一个新对象...也称为 item
。这不会起作用。永远。如果你正在尝试删除 item.selected
,那么您可以像这样使用解构:
...
} else {
let {selected, ...cleanedItem} = item;
item.selected && updating.push(cleanedItem);
!item.selected && updating.push(item);
}
...
在你的其他情况下,你也可以从 item
delete selected
。 delete
确实会改变原始对象,通常最好避免这种情况,但如果您知道它是安全的(取决于您的代码的其余部分),那么它是一个有效的选项。这是一个例子:
...
} else {
delete item.selected;
updating.push(item);
}
...
第三种删除selected is to do the same thing you do in your true case, but setting
selectedto
undefined`的方法:
...
} else {
updating.push({...item, selected: undefined});
}
...
但是,如果你走那条路,你也可以一起摆脱 if
并使用 ternary operator (expresion ? [true case] : [false case]
) 代替。它不能在这两种情况下执行复杂的逻辑,但您不需要这样做。看起来像这样:
...
// replacing the if/else
updating.push({
...item,
selected: item.value == e.target.value
? true
: undefined
});
...
或者,如果 false 对 selected
有效,您可以跳过任何条件分支:
...
// replacing the if/else
updating.push({
...item,
selected: item.value == e.target.value
});
...
当我们这样做时,您可能想要一起放弃对 updating
数组的推送。 Map,不像forEach
,是设计成return一个数组。只是 return 您要为数组中的项目设置的值:
const onChoiceChange = function setChoiceStateAndUpdateSelectedObject(e) {
let updating = choices.map((item, index) => {
return {
...item,
selected: item.value == e.target.value
}
});
setChoices(updating)
console.log('updating', updating)
}
把它们放在一起(折叠,因为这个答案很长):
let choices = [
{ value: 1, text: 'This is value 1' },
{ value: 2, text: 'This is value 2' },
{ value: 3, text: 'This is value 3' },
{ value: 4, text: 'this is value 4' }
];
document.addEventListener('input', (e) => {
let updating = [];
if (e.target.getAttribute('name') == "choices") {
updating = choices.map(item => ({
...item,
selected: item.value == e.target.value
}));
}
console.log(updating)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<input type='radio' name='choices' value='1' />
<input type='radio' name='choices' value='2' />
<input type='radio' name='choices' value='3' />
<input type='radio' name='choices' value='4' />
作为临别注,首先要说明语法错误的原因。上面关于解构的部分提到了它,但我想我会直接解决它。解构时,您需要使用声明性关键字 (let
, const, or
var`) 来创建新变量,或者使用现有变量和括号。 您不能混合搭配,您需要使用所有新变量或重用所有现有变量。像这样:
// new variables
// - can't be the same name as a defined variable in scope
let {selected, ...cleanedItem} = item;
// or with existing variables
// - the existing variables must be in scope
// - we'll assume item is in scope, same as your examples
let selected;
({selected, ...item} = item);
所以你得到语法错误的原因是因为你试图将新旧变量混合在一起。 selected
(正如其他人所指出的)未定义。除此之外(虽然不会抛出任何错误)如果你尝试 return 解构的结果,你实际上 return 你正在解构的未修改的原始项目。所以 selected
根本不会被删除,即使解构语法被正确使用。好玩,不是吗?
您定义的其他情况在逻辑上不正确。映射函数 returns 一个被映射类型的对象。所以你可以直接将 return 分配给一个变量。
let updating = choices.map((item, index) => { /* logic */}
否则,您可以简单地推送到更新数组,或者如上所述,您可以简单地 return 地图中的项目。
let updating = choices.map((item, index) => {
if (item.value == e.target.value) {
return {...item, selected: true};
} else {
return item;
// can push as below if you are not returning from map
// updating.push(item);
});
我正在创建单选按钮对象。数组中的每个对象都有对象 {value: 1, text: 'Sometext'} 并且如果单选按钮是 selected,添加 selected: true 到对象中并删除 select来自其他人。
const onChoiceChange = function setChoiceStateAndUpdateSelectedObject(e) {
let updating = []
choices.map((item, index) => {
if (item.value == e.target.value) {
updating.push({...item, selected: true})
} else {
item.selected && updating.push({selected, ...item} = item) //here it says selected undefined even with the condition check
!item.selected && updating.push(item)
}
})
setChoices(updating)
console.log('updating', updating)
}
我在这里使用代码片段工具,它可以工作,但是当我在 NextJS 中编译我的代码时,出现以下错误。
我在片段中使用相同的代码,我不明白为什么当我第二次 select 一个不同的单选按钮时它说 selected 未定义。
let choices = [
{ value: 1, text: 'This is value 1' },
{ value: 2, text: 'This is value 2' },
{ value: 3, text: 'This is value 3' },
{ value: 4, text: 'this is value 4'}
]
document.addEventListener('input',(e)=>{
let updating = []
if(e.target.getAttribute('name')=="choices") {
choices.map((item, index) => {
if (item.value == e.target.value) {
updating.push({...item, selected: true})
} else {
item.selected && updating.push({selected, ...item} = item)
!item.selected && updating.push(item)
}
})
}
console.log(updating)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<input type='radio' name='choices' value='1'/>
<input type='radio' name='choices' value='2'/>
<input type='radio' name='choices' value='3'/>
<input type='radio' name='choices' value='4'/>
请将 else 块中的行更新为
item.selected && updating.push(item) //
好的,所以 selected 对于解析器来说是未知的 variable/entity 因为您没有在代码中的任何地方定义。 selected:item.selected
将使 selected:true
.
请在下面找到工作片段:
let choices = [{
value: 1,
text: 'This is value 1'
},
{
value: 2,
text: 'This is value 2'
},
{
value: 3,
text: 'This is value 3'
},
{
value: 4,
text: 'this is value 4'
}
]
document.addEventListener('input', (e) => {
let updating = []
if (e.target.getAttribute('name') == "choices") {
choices.map((item, index) => {
if (item.value == e.target.value) {
updating.push({ ...item,
selected: true
})
} else {
item.selected && updating.push({
selected:item.selected,
...item
} = item)
!item.selected && updating.push(item)
}
})
}
console.log(updating)
})
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
</head>
<body>
<input type='radio' name='choices' value='1' />
<input type='radio' name='choices' value='2' />
<input type='radio' name='choices' value='3' />
<input type='radio' name='choices' value='4' />
</body>
</html>
您正在混淆 rest and spread 语法。两者都是椭圆(...
),但基本上是相反的。
在您的真实情况下,您正在使用传播 {...item, selected: true}
,将 item
中的所有值设置为新对象,然后添加键 selected
(可能覆盖项目中的先前 selected
键)。工作正常。
在你的 else 情况下,你正在使用 rest(并且通过扩展,destructuring,{selected, ...item} = item
。解构(和 rest)仅是 asignment。解构创建新变量,或者,如果用括号括起来,则重新分配旧变量。休息,特别是意味着 "take all of the entries I didn't ask for by name and shove them into a new object called [blank]"。你不是在向数组添加新对象。你正在将 items.selected
的值分配给一个未定义的变量 selected
,并试图将 item
中的其余条目重新分配给一个新对象...也称为 item
。这不会起作用。永远。如果你正在尝试删除 item.selected
,那么您可以像这样使用解构:
...
} else {
let {selected, ...cleanedItem} = item;
item.selected && updating.push(cleanedItem);
!item.selected && updating.push(item);
}
...
在你的其他情况下,你也可以从 item
delete selected
。 delete
确实会改变原始对象,通常最好避免这种情况,但如果您知道它是安全的(取决于您的代码的其余部分),那么它是一个有效的选项。这是一个例子:
...
} else {
delete item.selected;
updating.push(item);
}
...
第三种删除selected is to do the same thing you do in your true case, but setting
selectedto
undefined`的方法:
...
} else {
updating.push({...item, selected: undefined});
}
...
但是,如果你走那条路,你也可以一起摆脱 if
并使用 ternary operator (expresion ? [true case] : [false case]
) 代替。它不能在这两种情况下执行复杂的逻辑,但您不需要这样做。看起来像这样:
...
// replacing the if/else
updating.push({
...item,
selected: item.value == e.target.value
? true
: undefined
});
...
或者,如果 false 对 selected
有效,您可以跳过任何条件分支:
...
// replacing the if/else
updating.push({
...item,
selected: item.value == e.target.value
});
...
当我们这样做时,您可能想要一起放弃对 updating
数组的推送。 Map,不像forEach
,是设计成return一个数组。只是 return 您要为数组中的项目设置的值:
const onChoiceChange = function setChoiceStateAndUpdateSelectedObject(e) {
let updating = choices.map((item, index) => {
return {
...item,
selected: item.value == e.target.value
}
});
setChoices(updating)
console.log('updating', updating)
}
把它们放在一起(折叠,因为这个答案很长):
let choices = [
{ value: 1, text: 'This is value 1' },
{ value: 2, text: 'This is value 2' },
{ value: 3, text: 'This is value 3' },
{ value: 4, text: 'this is value 4' }
];
document.addEventListener('input', (e) => {
let updating = [];
if (e.target.getAttribute('name') == "choices") {
updating = choices.map(item => ({
...item,
selected: item.value == e.target.value
}));
}
console.log(updating)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<input type='radio' name='choices' value='1' />
<input type='radio' name='choices' value='2' />
<input type='radio' name='choices' value='3' />
<input type='radio' name='choices' value='4' />
作为临别注,首先要说明语法错误的原因。上面关于解构的部分提到了它,但我想我会直接解决它。解构时,您需要使用声明性关键字 (let
, const, or
var`) 来创建新变量,或者使用现有变量和括号。 您不能混合搭配,您需要使用所有新变量或重用所有现有变量。像这样:
// new variables
// - can't be the same name as a defined variable in scope
let {selected, ...cleanedItem} = item;
// or with existing variables
// - the existing variables must be in scope
// - we'll assume item is in scope, same as your examples
let selected;
({selected, ...item} = item);
所以你得到语法错误的原因是因为你试图将新旧变量混合在一起。 selected
(正如其他人所指出的)未定义。除此之外(虽然不会抛出任何错误)如果你尝试 return 解构的结果,你实际上 return 你正在解构的未修改的原始项目。所以 selected
根本不会被删除,即使解构语法被正确使用。好玩,不是吗?
您定义的其他情况在逻辑上不正确。映射函数 returns 一个被映射类型的对象。所以你可以直接将 return 分配给一个变量。
let updating = choices.map((item, index) => { /* logic */}
否则,您可以简单地推送到更新数组,或者如上所述,您可以简单地 return 地图中的项目。
let updating = choices.map((item, index) => {
if (item.value == e.target.value) {
return {...item, selected: true};
} else {
return item;
// can push as below if you are not returning from map
// updating.push(item);
});