Reputation: 44093
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)
Upvotes: 2
Views: 1161
Reputation: 24638
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"]}))[0];
console.log( data );
Upvotes: 0
Reputation: 8107
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)
Upvotes: 0
Reputation: 13500
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.
Upvotes: 0
Reputation: 89394
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);
Upvotes: 1
Reputation: 386680
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; }
Upvotes: 2