Reputation: 1942
I need to concat items to an array stored in React component state. I have an example on stackblitz and I cant understand why the array is not growing as i add elements using spread operator to concatenate to the existing array. Any help appreciated
link: https://stackblitz.com/edit/react-usestate-example-ebzt6g?file=index.js
import React from 'react';
import { useState, useEffect } from 'react';
import { render } from 'react-dom';
import './style.css';
const App = () => {
const [name, setName] = useState('React');
const [coords, setCoords] = useState([]);
const success = (position) => {
// setCoords(coords.concat(position.coords))
setCoords([
...coords,
position.coords
])
console.log("success! position=", position);
}
useEffect(() => {
console.log("useEffect -> coords =", coords);
});
useEffect(() => {
setInterval(() => {
success({coords : {latitude: Math.random()*51, longitude: Math.random()*2.6}});
}, 5000);
}, []);
return (
<p>example to demonstrate growing an array stored with React usestate hook</p>
)
}
render(<App />, document.getElementById('root'));
Upvotes: 2
Views: 6454
Reputation: 1942
Thanks Nicholas Tower for the correct answer.
const success = (position) => {
setCoords(prevCoords => {
return [
...prevCoords,
position.coords
]
})
}
fixes the issue.
Upvotes: 2
Reputation: 1042
Well, I had that problem and thanks to someone who helped me figure out how to solve that problem, first you have to clone the coords, and then u add the new coords to the clone and then you set the new clone coords to the state like this:
const success = (position) => {
let clonedCoords = [...coords];
setCoords([...clonesCoords, position.coords]);
console.log("success! position=", position);
};
this should work, if it doesn't you can reply so I can help u more
Upvotes: -1
Reputation: 85012
useEffect(() => {
setInterval(() => {
success({coords : {latitude: Math.random()*51, longitude: Math.random()*2.6}});
}, 5000);
}, []);
The empty array as the second parameter tells react to create this effect only once, and never update it. When it's created, it has a reference to the success function in its closure, and that success function in turn has a reference to coords
. Since this is all from the first render, coords
is an empty array.
So every time you call success
, you're adding the new coords to that empty array and calling setCoords. The array never grows, because your starting point is always the empty array. And you'll never see the new arrays because those only exist on later renders.
The simplest fix for this is to use the function version of setCoords. React will call the function and pass in the latest value of coords
const success = (position) => {
setCoords(prevCoords => {
return [
...prevCoords,
position.coords
]
})
}
Upvotes: 7