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

Viewed 35658

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})
8 Answers

You can convert the array to objects (the ...array1), replace the item (the [1]:"seven"), then convert it back to an array (Object.values) :

array1 = ["one", "two", "three"];
array2 = Object.values({...array1, [1]:"seven"});
console.log(array1);
console.log(array2);

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
 ]

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

If you 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)]})

first find the index, here I use the image document id docId as illustration:

const index = images.findIndex((prevPhoto)=>prevPhoto.docId === docId)
this.setState({images: [...this.state.images.slice(0,index), updatedImage, ...this.state.images.slice(index+1)]})

I have tried a lot of using the spread operator. I think when you use splice() it changes the main array. So the solution I discovered is to clone the array in new variables and then split it using the spread operator. The example I used.

var cart = [];

function addItem(item) {
    let name = item.name;
    let price = item.price;
    let count = item.count;
    let id = item.id;

    cart.push({
        id,
        name,
        price,
        count,
    });

    return;
}

function removeItem(id) {
    let itemExist = false;
    let index = 0;
    for (let j = 0; j < cart.length; j++) {
        if (cart[j].id === id) { itemExist = true; break; }
        index++;
    }
    if (itemExist) {
        cart.splice(index, 1);
    }
    return;
}

function changeCount(id, newCount) {
    let itemExist = false;
    let index = 0;
    for (let j = 0; j < cart.length; j++) {
        console.log("J: ", j)
        if (cart[j].id === id) {
            itemExist = true;
            index = j;
            break;
        }
    }
    console.log(index);
    if (itemExist) {
        let temp1 = [...cart];
        let temp2 = [...cart];
        let temp3 = [...cart];
        cart = [...temp1.splice(0, index),
            {
                ...temp2[index],
                count: newCount
            },
            ...temp3.splice(index + 1, cart.length)
        ];
    }

    return;
}

addItem({
    id: 1,
    name: "item 1",
    price: 10,
    count: 1
});
addItem({
    id: 2,
    name: "item 2",
    price: 11,
    count: 1
});
addItem({
    id: 3,
    name: "item 3",
    price: 12,
    count: 2
});
addItem({
    id: 4,
    name: "item 4",
    price: 13,
    count: 2
});

changeCount(4, 5);
console.log("AFTER CHANGE!");
console.log(cart);
Related