0

I have this react code, and I am selecting an item from the array with find() method.

Does JS copy the item from the array or returns a reference?

EDIT: My items in array are objects, like [{id: 12, name: "Peter"}, {id: 13, name: "Dorothy"}...]

this.setState(prevState => {

    const items = [...prevState.items];
    const itemToCopy = items.find(item => item.id === copiedItemId);

    if(!itemToCopy) {
        console.warn("Can not find an item to be copied!", copiedItemId, items, itemToCopy);
        return null;
    }

    //is the variable "itemToCopy" a reference to item in the array or it is the new (copied) object itself?

    itemToCopy.id = null;
    itemToCopy.tempId = Math.random();
    itemToCopy.actionBeingProcessed = "copy";
    itemToCopy.date_raw = copyToDate;

    //if I push it into the array, react tells me it has duplicate "tempId"
    items.push(itemToCopy);

    return {
        items: sortItems(items)
    };
}
Ivan Hanák
  • 2,214
  • 1
  • 16
  • 25
  • 3
    Your code updates an existing item and adds it to the same list a second time. – Thilo Nov 27 '17 at 10:58
  • 1
    It actually depends on the type of the item. Primitive types like string, boolean, integer are passed by value, but objects are "passed by reference" (actually the reference of the object is passed by value, but ends the same) – Kaddath Nov 27 '17 at 11:00
  • @Thilo dude, all right, exactly as I though - what, according to you, would be a correct way of making it the right way? should I use `Object,assign()`? Because my object has a depth of 3. – Ivan Hanák Nov 27 '17 at 11:00
  • 1
    Longish thread about this: https://stackoverflow.com/q/518000/14955 – Thilo Nov 27 '17 at 11:01
  • @IvanHanák There is no generic way to "deep-clone" objects. I suggest you add a "copy-constructor" method for the particular case that you need. – Thilo Nov 27 '17 at 11:04

2 Answers2

1

Yes, it does it by reference, but you can just clone the object using Object.assign or the spread operator. Someone mentioned something about deep cloning. This is not necessary if the values in your object are always primitives.

this.setState(prevState => {
    const items = [...prevState.items];
    const itemToCopy = items.find(item => item.id === copiedItemId);

    if(!itemToCopy) {
        console.warn("Can not find an item to be copied!", copiedItemId, items, itemToCopy);
        return null;
    }

    //is the variable "itemToCopy" a reference to item in the array or it is the new (copied) object itself?
    const tempItem = {...itemToCopy} //new object
    tempItem.id = null;
    tempItem.tempId = Math.random();
    tempItem.actionBeingProcessed = "copy";
    tempItem.date_raw = copyToDate;

    //if I push it into the array, react tells me it has duplicate "tempId"
    items.push(tempItem);

    return {
        items: sortItems(items)
    };
}
Andrew
  • 7,201
  • 5
  • 25
  • 34
0

You’re setting items as an array, and then pushing the augmented items back into the same array. Try creating a second variable like augmentedItems, pushing to that, and returning that array instead.

Hope this helps!

patn889
  • 16