'React array not changing with setState [duplicate]
My array isn't getting new entries added to it via the setState getter.
Code:
let calledOut = false;
export default function PayStation () {
const [records, setRecords] = useState([]);
// problem snippet
if (records.length === 0 && !calledOut) {
calledOut = true;
fetch('http://localhost:5000/api').then(
response => response.json()
).then(
data => {
const payloadRecords = data["records"];
// returning
// [{
// "attributes": {
// "type": "Contact",
// "url": "/services/data/v42.0/sobjects/Contact/0030U00001UPWYKQA5"
// },
// "Id": "0030U00001UPWYKQA5",
// "Name": "Contact25 Sequence Contact Manual Email"
// },
// {
// "attributes": {
// "type": "Contact",
// "url": "/services/data/v42.0/sobjects/Contact/0030U00001UPWYLQA5"
// },
// "Id": "0030U00001UPWYLQA5",
// "Name": "Contact26 Sequence Contact Manual Email"
// }
// ]
setRecords((records => [...records, ...payloadRecords]));
console.log("records size: " + records.length); // why is this still 0?
}
);
}
// end problem snippet
return (records.length === 0 ? "loading..." :
<div style={{
height: '100vh',
display: 'flex',
maxWidth: 600,
justifyContent: 'space-between',
alignItems: 'center'
}} >
{records}
</div>
);
}
I think the requirement for state to change is that you clone the state variable (which I believe I'm doing), as opposed to assigning a reference to it and mutating the reference.
So, why isn't my array getting new entries?
Solution 1:[1]
The body of the component should be a pure function. Side effects (such as data fetching) should be wrapped in useEffect. The following code should work:
export default function PayStation () {
const [records, setRecords] = useState([]);
useEffect(() => {
const getRecords = () => {
fetch('http://localhost:5000/api').then(
response => response.json()
).then(
data => {
const payloadRecords = data["records"];
setRecords((records => [...records, ...payloadRecords]));
}
);
}
getRecords()
}, [])
if (records.length === 0) return "loading..."
return (
<div style={{
height: '100vh',
display: 'flex',
maxWidth: 600,
justifyContent: 'space-between',
alignItems: 'center'
}} >
{records.map((record) => <Record key={record.id} {...record} />)}
</div>
);
}
Solution 2:[2]
The issue seems to be that useState and setState are both being ran in the same call... And since they're both async the setState isn't setting a value to anything since the state hasn't been created yet. If you removed the calledOut variable it should work fine.
This is generally bad way to do fetching. I recommend doing
useEffect(() => {
// fetch stuff here
}, []);
So this will be invoked after the states are made.
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 | Stafford Rose |
| Solution 2 | Bas bas |
