I’m having a problem where an array that I have stored as a useState object is only getting its last element updated. In the below example, we maintain an array of objects that we update in Sub. If we change such a for loop to iterate through all the elements in arr, it is consistent behavior that the last element in arr will be the only one that gets updated.
function Sub({arr, setArr}) {
useEffect(() => {
for(let i = 0; i < 2; i++){
const arr_copy = arr.slice()
arr_copy[i] = i
setArr(arr_copy)
}
},[])
return <p> </p>
}
export function App(props) {
const [arr, setArr] = useState(["NOT CHANGED","NOT CHANGED"])
return (
<div className='App'>
{arr.map((d) => <p> {d} </p>)}
<Sub arr={arr} setArr = {setArr}/>
</div>
);
}
Renders:
NOT CHANGED
1
I’ve tried the suggested answers in this thread – these all being different variations of "pass in a callback to the setfunction", "first set the array to an empty array," "create deep copy" and none of these seem to work (all resulting in the same behavior of the last element of the array being the only one changed).
As a further note I get the same behavior for useState({...}) where I populate and update a dictionary as opposed to a list.
>Solution :
The problem is not with the useState its your own code.
on the first line inside of the for loop you define a new array so every time its a new array with the same values as the original array.
let me explain this with step by step guide:
i = 0:
1 - arr_copy = ["NOT CHANGED","NOT CHANGED"]
2 - arr_copy = [0,"NOT CHANGED"]
3 - setArray([0,"NOT CHANGED"])
i = 1:
1 - arr_copy = ["NOT CHANGED","NOT CHANGED"]
2 - arr_copy = ["NOT CHANGED", 1]
3 - setArray(["NOT CHANGED", 1])