-1

Trust you are having a great day!

I'm running into a serious issue with React. I have a state which holds an array. In a function I copy the state into a new variable. When I modify this newly defined variable it also updates the state which is not what I want.

Example:

const [arrayState, setArrayState] = useState(
    [
        {
            id: 'ID_1'
            text: 'item 1',
        },
        {
            id: 'ID_2'
            text: 'item 2',
        },
        {
            id: 'ID_3'
            text: 'item 3',
        },
        {
            id: 'ID_4'
            text: 'item 4',
        },
    ]
);

const myFunction = () => {
    let myVariable = [...arrayState];

    myVariable[1].text = 'myVariable item 2'; // This is modifying arrayState as well which is wrong

};

I only want myVariable to be modified and not my state (arrayState) as well.

John
  • 15
  • 5
  • Does this answer your question? [How to update state with usestate in an array of objects?](https://stackoverflow.com/questions/62918710/how-to-update-state-with-usestate-in-an-array-of-objects) – pilchard Jun 13 '23 at 00:09
  • 1
    or [What is the most efficient way to deep clone an object in JavaScript?](https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript) – pilchard Jun 13 '23 at 00:12
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax#sect1 – Dave Newton Jun 13 '23 at 03:07

2 Answers2

1

You can use structuredClone to make a deep clone of the array of objects.

let myVariable = structuredClone(arrayState);

Alternatively, a solution that only works for this specific data structure:

let myVariable = arrayState.map(o => ({...o}));
Unmitigated
  • 76,500
  • 11
  • 62
  • 80
0

It has to do with primitive and reference values. Arrays and objects do not store values, but they refer to addresses in memory where values ​​are stored. A simple example:

const func = () => {
    // Same memory reference
    const temp = arrayState;
    temp[1] = "4";
    setAttayState(temp);
}

above code does not re-render because reference of the value has not changed.

You have to assign new reference address like this:

const func = () => {

    // Create new reference
    const temp = [...arrayState];
    temp[1] = "4";
    setAttayState(temp);
}
somerandomusername
  • 1,993
  • 4
  • 23
  • 55
  • Really appreciate your comment! My issue is not updating the state, however it is that when I update `myVariable` that `arrayState` is unexpectedly being modified as well – John Jun 12 '23 at 23:35
  • On my end `let myVariable = [...arrayState];` is also changing `arrayState` which should not be happening unless I use `setArrayState();` – John Jun 12 '23 at 23:38
  • That is related to shallow copy, in this case you have to totally create new arry in your method. like let newArray : any[] = []; – Humanoid Mk.12 Jun 12 '23 at 23:51
  • @John When you say "`myVariable = [...arrayState]` is also changing `arrayState`" it confuses people. That **can't** change `arrayState`, which is changed **after** that when you modify an object property in `myVariable`. **Then** an object in `arrayState` is changed because it's the same object that's in `myVariable`, because `myVariable` and `arrayState` are both arrays *(but different arrays)* of the same objects. – Dave Newton Jun 13 '23 at 03:10