Replace array entry with spread syntax in one line of code?
Object.assign
does the job:
this.setState({images: Object.assign([], this.state.images, {4: updatedImage}));
...but involves a temporary object (the one at the end). Still, just the one temp object... If you do this with slice
and spreading out arrays, it involve several more temporary objects (the two arrays from slice
, the iterators for them, the result objects created by calling the iterator's next
function [inside the ...
handle], etc.).
It works because normal JS arrays aren't really arrays1(this is subject to optimization, of course), they're objects with some special features. Their "indexes" are actually property names meeting certain criteria2. So there, we're spreading out this.state.images
into a new array, passing that into Object.assign
as the target, and giving Object.assign
an object with a property named "4"
(yes, it ends up being a string but we're allowed to write it as a number) with the value we want to update.
Live Example:
const a = [0, 1, 2, 3, 4, 5, 6, 7];
const b = Object.assign([], a, {4: "four"});
console.log(b);
If the 4
can be variable, that's fine, you can use a computed property name (new in ES2015):
let n = 4;
this.setState({images: Object.assign([], this.state.images, {[n]: updatedImage}));
Note the []
around n
.
Live Example:
const a = [0, 1, 2, 3, 4, 5, 6, 7];
const index = 4;
const b = Object.assign([], a, {[index]: "four"});
console.log(b);
1 Disclosure: That's a post on my anemic little blog.
2 It's the second paragraph after the bullet list:
An integer index is a String-valued property key that is a canonical numeric String (see 7.1.16) and whose numeric value is either +0 or a positive integer ≤ 253-1. An array index is an integer index whose numeric value i is in the range +0 ≤ i < 232-1.
So that Object.assign
does the same thing as your create-the-array-then-update-index-4.
use Array.slice
this.setState({images: [...this.state.images.slice(0, 4), updatedImage, ...this.state.images.slice(5)]})
Edit from original post: changed the 3 o a 4 in the second parameter of the slice method since the second parameter points to the member of the array that is beyond the last one kept, it now correctly answers the original question.