Replace array entry with spread syntax in one line of code?

ε祈祈猫儿з 提交于 2020-01-12 14:03:13

问题


I'm replacing an item in a react state array by using the ... spread syntax. This works:

let newImages = [...this.state.images]
newImages[4] = updatedImage
this.setState({images:newImages})

Would it be possible to do this in one line of code? Something like this? (this doesn't work obviously...)

this.setState({images: [...this.state.images, [4]:updatedImage})

回答1:


use Array.slice

this.setState({images: [...this.state.images.slice(0, 3), updatedImage, ...this.state.images.slice(4)]})



回答2:


There's no syntax that provides that, no. 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...

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.


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.




回答3:


You can use map:

const newImages = this.state.images
  .map((image, index) => index === 4 ? updatedImage : image)



回答4:


Here is my self explaning non-one-liner

 const wantedIndex = 4;
 const oldArray = state.posts; // example

 const updated = {
     ...oldArray[wantedIndex], 
     read: !oldArray[wantedIndex].read // attributes to change...
 } 

 const before = oldArray.slice(0, wantedIndex); 
 const after = oldArray.slice(wantedIndex + 1);

 const menu = [
     ...before,  
     updated,
     ...after
 ]



回答5:


I refer to @Bardia Rastin solution, and I found that the solution has mistake at the index value (it replaces item at index 3 but not 4).

if want to replace the item which has index value, index, the answer should be

this.setState({images: [...this.state.images.slice(0, index), updatedImage, ...this.state.images.slice(index + 1)]})

this.state.images.slice(0, index) is a new array has items start from 0 to index - 1 (index is not included)

this.state.images.slice(index) is a new array has items starts from index and afterwards.

To correctly replace item at index 4, answer should be

this.setState({images: [...this.state.images.slice(0, 4), updatedImage, ...this.state.images.slice(5)]})


来源:https://stackoverflow.com/questions/45673783/replace-array-entry-with-spread-syntax-in-one-line-of-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!