Возвращает измененный объект с некоторым ключом, измененным с помощью оператора распространения

#javascript #reactjs #redux #spread

#javascript #reactjs #сокращение #распространение

Вопрос:

В приведенном ниже объекте я хочу увеличить значение val для data[1] на 1 и оставить все без изменений, как я могу этого добиться?

 const state = 
    {
        "data": [{
                "val": 1,
                "other": 10
            },
            {
                "val": 11,
                "other": 100
            },
            {
                "val": 100,
                "other": 1000
            }
        ]
    }
 

Я хочу, чтобы мутировавший объект был таким-

 {
    "data": [{
            "val": 1,
            "other": 10
        },
        {
            "val": 10,
            "other": 100
        },
        {
            "val": 100,
            "other": 1000
        }
    ]
}
 

Я знаю, что я могу изменить значение напрямую, как это — state.data[1].val = state.data[1].val 1 , но я хочу добиться того же, используя оператор распространения, возможно ли достичь этого с помощью оператора распространения?
Что-то вроде этого-

 const mutatedState = {
        ...state,
        data: [...state.data]
}
 

Комментарии:

1. Работа с глубокими объектами и неизменяемостью может быть настоящей болью, поэтому что-то вроде помощников по функциональному программированию Lodash может значительно облегчить вашу жизнь. посмотрите вверх: Lodash/fp/set

Ответ №1:

Извлеките data из объекта. И используйте так

 const state = { "data": [{ "val": 1, "other": 10 }, { "val": 11, "other": 100 }, { "val": 100, "other": 1000 } ] }
    
const {data} = state;         
let res = {
            ...state,
            data:[
                    data[0],
                    {...data[1],val:data[1].val  1},
                    ...data.slice(2)
                 ]
          }
 
console.log(result) 

Ответ №2:

Вы можете назначить части массива / объектов.

 var object = { data: [{ val: 1, other: 10 }, { val: 10, other: 100 }, { val: 100, other: 1000 }] },
    result = {
        ...object,
        data: Object.assign(
            [...object.data],
            {
                1: Object.assign(
                    {},
                    object.data[1],
                    { val: object.data[1].val   1 }
                )
            }
        )
    };

console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

Ответ №3:

С небольшой помощью некоторых функциональных помощников это на самом деле довольно элегантно:

  const mapOne = (index, mapper) => array => array.map((it, i) => i === index ? mapper(it) : it);
 const lens = (key, mapper) => obj => ({ ...obj, [key]: mapper(obj[key]) });

 // somewhere
 this.setState(mapOne(1, lens("val", it => it   1)));