如何使用JavaScript Spread ...语法更改对象的一个​​字段,该字段属于数组,并且由名称/值对访问?

问题描述

这是代码(无法在构建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']);

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...