如何使用 JavaScript spread... 语法更改属于数组并通过名称-值对访问的对象的一个字段?
How to use JavaScript spread... syntax to change the one field of the object, that belongs to the array and is accessed by name-value pair?
代码如下(在构建state2的语句处编译失败,即在第二次传播时):
let line_id = 6;
let state = {
invoice: {
id: 1015,
description: 'web order',
},
lines: [
{id: 5, description: 'phone', color: 'black'},
{id: 6, description: 'tablet', color: 'blue'},
{id: 7, description: 'computer', color: 'gray'},
]
};
//this alert and this access pattern works, so, I would like to use
//.find... to access element in spread... structure as well
//alert(state['lines'].find(line=>line['id']==line_id)['description']);
let state2 = {
...state,
['lines']: { ...state['lines'],
find(line=>line['id']==line_id): { ...state['lines'].find(line=>line['id']==line_id),
['description']: 'TV',
},
},
};
alert(state2['lines'].find(line=>line['id']==line_id)['description']);
我有 state
结构,我访问 lines
数组,我通过名称-值对访问特定行 id=6
我想更改字段的值 description
。这项工作是 的延续,我在其中尝试创建通用过程,该过程使用 spread... 语法和按名称访问策略来更新复杂的 object/array 树。事实上 - 这个复杂的树是 Redux reducer 的状态,并且更新发生在处理 AgGrid 的 valueSetter
函数的操作中。但是 - 这本身就是一个有趣的练习,可以更好地理解传播...以及 JavaScript 和 JSON 中的结构 JavaScript.
所以 - 唯一的问题是:如何写行
find(line=>line['id']==line_id): { ...state['lines'].find(line=>line['id']==line_id),
以便代码编译?如何在此设置中通过名称-值对访问数组的特定元素:
请注意,我正在尝试构建通用代码:
find(line=>line[keyFieldName]==keyFieldValue): { ...state['lines'].find(line=>line[keyFieldName]==keyFieldValue),
使用任意字段名称和字段值 - 这样的处理程序可以在 React/Redux 设置中更新任意 2D AgGrid 的任意记录的任意字段。
我的代码的预期结果:1) 它应该编译; 2) 第二个警报应该 return 'TV'.
如果我正确理解了你想要实现的目标,这应该可行:
let line_id = 6;
let state = {
invoice: {
id: 1015,
description: 'web order',
},
lines: [{
id: 5,
description: 'phone',
color: 'black'
},
{
id: 6,
description: 'tablet',
color: 'blue'
},
{
id: 7,
description: 'computer',
color: 'gray'
},
]
};
const stateKeyId = 'lines';
const itemKeyId = 'id';
const itemAttr = 'description'
let state2 = {
...state,
[stateKeyId]: state[stateKeyId].map(item => {
if (item[itemKeyId] == line_id) {
return ({
...item,
[itemAttr]: 'TV'
});
}
return item
})
}
console.log(state2);
find(line=>line['id']==line_id)
应该变成 [find(line=>line['id']==line_id)]
,因为就像字符串一样,它必须在方括号之间才能使 js 正常工作。
此外,如果您使用 lodash
中的 find
,它将 return 对象,因此如果您需要使用 id 作为键,您可以执行以下操作:
[get(find(line => line['id'] === line_id]), 'id')]: whatever
一些观察结果:
- 总是请总是在 js 中使用 === 而不是 ==
- 避免snake_case,在 js 中使用驼峰式大小写,因为它是标准的
- 您的代码实际上并没有正确处理丢失的项目,如果您需要这样做,请将其分成多行,因为这样会更容易理解
您可以使用 map 方法从数组到 return 个基于原始元素的不同元素。
以下是您的使用方法:
line_id = 6;
state = {
invoice: {
id: 1015,
description: 'web order',
},
lines: [
{id: 5, description: 'phone', color: 'black'},
{id: 6, description: 'tablet', color: 'blue'},
{id: 7, description: 'computer', color: 'gray'},
]
};
state2 = {
...state,
lines: state.lines.map(line => {
if (line.id === line_id)
return { ...line, description: 'YT' }
return { ...line }
})
};
alert(state2['lines'].find(line=>line['id']==line_id)['description']);
代码如下(在构建state2的语句处编译失败,即在第二次传播时):
let line_id = 6;
let state = {
invoice: {
id: 1015,
description: 'web order',
},
lines: [
{id: 5, description: 'phone', color: 'black'},
{id: 6, description: 'tablet', color: 'blue'},
{id: 7, description: 'computer', color: 'gray'},
]
};
//this alert and this access pattern works, so, I would like to use
//.find... to access element in spread... structure as well
//alert(state['lines'].find(line=>line['id']==line_id)['description']);
let state2 = {
...state,
['lines']: { ...state['lines'],
find(line=>line['id']==line_id): { ...state['lines'].find(line=>line['id']==line_id),
['description']: 'TV',
},
},
};
alert(state2['lines'].find(line=>line['id']==line_id)['description']);
我有 state
结构,我访问 lines
数组,我通过名称-值对访问特定行 id=6
我想更改字段的值 description
。这项工作是 valueSetter
函数的操作中。但是 - 这本身就是一个有趣的练习,可以更好地理解传播...以及 JavaScript 和 JSON 中的结构 JavaScript.
所以 - 唯一的问题是:如何写行
find(line=>line['id']==line_id): { ...state['lines'].find(line=>line['id']==line_id),
以便代码编译?如何在此设置中通过名称-值对访问数组的特定元素:
请注意,我正在尝试构建通用代码:
find(line=>line[keyFieldName]==keyFieldValue): { ...state['lines'].find(line=>line[keyFieldName]==keyFieldValue),
使用任意字段名称和字段值 - 这样的处理程序可以在 React/Redux 设置中更新任意 2D AgGrid 的任意记录的任意字段。
我的代码的预期结果:1) 它应该编译; 2) 第二个警报应该 return 'TV'.
如果我正确理解了你想要实现的目标,这应该可行:
let line_id = 6;
let state = {
invoice: {
id: 1015,
description: 'web order',
},
lines: [{
id: 5,
description: 'phone',
color: 'black'
},
{
id: 6,
description: 'tablet',
color: 'blue'
},
{
id: 7,
description: 'computer',
color: 'gray'
},
]
};
const stateKeyId = 'lines';
const itemKeyId = 'id';
const itemAttr = 'description'
let state2 = {
...state,
[stateKeyId]: state[stateKeyId].map(item => {
if (item[itemKeyId] == line_id) {
return ({
...item,
[itemAttr]: 'TV'
});
}
return item
})
}
console.log(state2);
find(line=>line['id']==line_id)
应该变成 [find(line=>line['id']==line_id)]
,因为就像字符串一样,它必须在方括号之间才能使 js 正常工作。
此外,如果您使用 lodash
中的 find
,它将 return 对象,因此如果您需要使用 id 作为键,您可以执行以下操作:
[get(find(line => line['id'] === line_id]), 'id')]: whatever
一些观察结果:
- 总是请总是在 js 中使用 === 而不是 ==
- 避免snake_case,在 js 中使用驼峰式大小写,因为它是标准的
- 您的代码实际上并没有正确处理丢失的项目,如果您需要这样做,请将其分成多行,因为这样会更容易理解
您可以使用 map 方法从数组到 return 个基于原始元素的不同元素。
以下是您的使用方法:
line_id = 6;
state = {
invoice: {
id: 1015,
description: 'web order',
},
lines: [
{id: 5, description: 'phone', color: 'black'},
{id: 6, description: 'tablet', color: 'blue'},
{id: 7, description: 'computer', color: 'gray'},
]
};
state2 = {
...state,
lines: state.lines.map(line => {
if (line.id === line_id)
return { ...line, description: 'YT' }
return { ...line }
})
};
alert(state2['lines'].find(line=>line['id']==line_id)['description']);