Consider the following data:
let data = [
{ foo: true, bar: [ 1, 2, 3 ] },
{ foo: true, bar: [ 8, 9, ] }
];
I'm trying to push
something to the nested bar
array on index 1
using the spread syntax (...
).
So the final array should become:
[
{ foo: true, bar: [ 1, 2, 3 ] },
{ foo: true, bar: [ 8, 9, 'new-item' ] }
]
Normally, we'll just use push: data[1].bar.push(0)
, but I need a spread solution
I've tried to use this approach:
How to push new elements to a nested array of objects in JavaScript using spread syntax
data = [ ...data, {[1]: { ...data[1], bar: [ ...data[1].bar, 'new-item' ] } }]
But this will append another object with a single key 1
, it does not alter data[1]
.
Then, I've tried to use Object.assign()
but again ended up with a new index:
Replace array entry with spread syntax in one line of code?
data = [ ...data, Object.assign({}, data[1], { bar }})
tl;dr, How do I append something to an array, part of an object, that's inside an array of objects, using the spread syntax?
Please link me to a duplicate, or provide a way to do this
Playground:
let data = [
{ foo: true, bar: [ 1, 2, 3 ] },
{ foo: true, bar: [ 8, 9 ] }
];
// 'Regular' push method
// data[1].bar.push(0);
// Using spread reassign
// data = [ ...data, {[1]: { ...data[1], bar: [ ...data[1].bar, 'new-item' ] } }]
// Using Object.assign
data = [ ...data, Object.assign({}, data[1], {bar: [ 'new-item' ] } ) ];
console.log(data)
CodePudding user response:
You could take an outer Object.assign
with an array as target and an object with the index as key.
let
data = [
{ foo: true, bar: [1, 2, 3] },
{ foo: true, bar: [8, 9] }
];
data = Object.assign(
[...data], // target array
{ 1: { // array index as key
...data[1],
bar: [...data[1].bar, 'new-item']
} }
);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
CodePudding user response:
You can use Object.assign
on the array itself.
let data = [
{ foo: true, bar: [ 1, 2, 3 ] },
{ foo: true, bar: [ 8, 9, ] }
];
data = Object.assign([...data], {1: { ...data[1], bar: [...data[1].bar, 'new-item']}});
console.log(data);
CodePudding user response:
I don't think this is more readable than many other options open to you but this satisfies the requirement of "using object spread".
let data = [
{ foo: true, bar: [ 1, 2, 3 ] },
{ foo: true, bar: [ 8, 9, ] },
{ foo: false, bar: [ ] }
];
let idx = 1;
let newData = [
...data.slice(0, idx),
{
...data[idx],
bar: [ ...data[idx].bar, 'new-item' ]
},
...data.slice(idx 1)
];
console.log(newData);
This will first take your data and cut the array up to the item you wish to replace (index 1). A new object follows, then the rest of the array (if any) follows.
CodePudding user response:
First, treat the array like an object with numbered keys, and use the spread operator and override the necessary index. Then, use Object.values() to treat it like an array.
let data = [
{ foo: true, bar: [ 1, 2, 3 ] },
{ foo: true, bar: [ 8, 9, ] }
]
data = Object.values({ ...data, 1: { ...data[1], bar: [ ...data[1].bar, 'new-item' ] } })
console.log(data)
In this particular case, if the index you need to alter is near the beginning of the array, you can also use an IIFE to allow for a destructuring approach, like this:
let data = [
{ foo: true, bar: [ 1, 2, 3 ] },
{ foo: true, bar: [ 8, 9, ] }
]
data = (([first, {bar, ...rest}]) => [first, {...rest, bar:[...bar, 'new-item']}])(data)
console.log(data)
CodePudding user response:
You can just assign the first element index to the modified element that uses Array#map
and the spread operator as follows:
const data = [
{ foo: true, bar: [ 1, 2, 3 ] },
{ foo: true, bar: [ 8, 9, ] }
];
data[1] = [data[1]].map(({foo,bar}) => ({foo,bar:[...bar,"some new value"]}));
console.log( data );