'ReactJS push to state array replaces every exisitng value in array

I want to push an 2d array into the end of a state. But somehow, when i log the state every time it changes with a useEffect, i replaces every existing array with the new one.

The variable "position" is my 2d array, also a state. Might this cause any reference problems? I have no idea and im starting to lose my mind about this...

const [positionList, setPositionList] = useState([]);
useEffect(() => {
    const updatePosition = [...positionList, position]
    setPositionList(updatePosition);
}, [playerTurn])

expected output (or what i want)

positionList = [position1, position2, position3, //and so on]

but what i get is this (lets say i try to push the array three times)

positionList = [position3, position3, position3]

EDIT: So, after some good ideas from the community, i found out that i had to copy my array i want to push (the "position") before i push it into the state. So my working code looks now like this:

const [positionList, setPositionList] = useState([])
useEffect(() => {
    let positionCopy = [];
    for (let i = 0; i < position.length; i++) {
        positionCopy[i] = position[i].slice();
    }
    setPositionList([...positionList, positionCopy]);
}


Solution 1:[1]

You didn't add positionList as a dependency of your useEffect callback, so the positionList captured by the callback doesn't necessarily reflect the latest value.

useEffect(() => {
    // return early if the update already happened to prevent recursion
    const updatePosition = [...positionList, position]
    setPositionList(updatePosition);
}, [playerTurn, positionList])

TBH, using useEffect to update a state hook is difficult to maintain and prone to accidental recursive behaviour.

You might get better mileage by using a state reducer with the useReducer hook. For anything beyond trivial state management, the useReducer hook is worth getting to grips with.

Solution 2:[2]

try:

 const [positionList, setPositionList] = useState([]);
 useEffect(() => {
     setPositionList(state=> [...state, position]);
 }, [playerTurn])

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Adem79