问题描述
这是代码(无法在构建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
访问了特定行,并且我想更改字段{{1 }}。这项工作是https://stackoverflow.com/a/64116308/1375882的延续,我在其中尝试创建通用过程,该过程使用spread ...语法和按名称访问策略来更新复杂的对象/数组树。实际上,这棵复杂的树是Redux reducer的状态,并且该更新发生在处理AgGrid的description
函数的操作中。但是,这本身就是一个有趣的练习,它可以用来更好地理解传播...以及JavaScript中的JavaScript和JSON结构。
所以-唯一的问题是:如何写行
valueSetter
以便代码可以编译?如何在此设置中按名称/值对访问数组的某些元素:
请注意,我正在尝试构建通用代码:
find(line=>line['id']==line_id): { ...state['lines'].find(line=>line['id']==line_id),
使用任意字段名称和字段值-这样的处理程序可以在React / Redux设置中更新任意2D AgGrid的任何记录的任何字段。
我的代码的预期结果:1)应该编译; 2)第二个警报应返回“ 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正常工作。
此外,如果您使用find
中的lodash
,它将返回该对象,因此,如果您需要使用id作为键,则可以执行以下操作:
[get(find(line => line['id'] === line_id]),'id')]: whatever
一些观察结果
- 始终在js中始终使用===而不是==
- 避免snake_case,因为它是标准的,所以将camelCase与js一起使用
- 您的代码实际上并不是在处理丢失的项目的正确性,如果您需要这样做,则将其拆分为多行,因为这样更容易理解
您可以使用数组中的map方法来基于原始元素返回不同的元素。
这里是使用方式:
line_id = 6;
state = {
invoice: {
id: 1015,lines: [
{id: 5,color: 'black'},{id: 6,color: 'blue'},{id: 7,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']);