I have a useEffect that triggers fine. When it fires, I'd like to to go out to X number of calls to an API (getQueueMetrics
) and basically 'fillup' the queueMetrics
state value as they resolve.
const [queueMetrics, setQueueMetrics] = useState()
useEffect(() => {
QUEUE_NAMES_ARR.forEach(qName => {
getQueueMetrics(qName)
.then((qMetric) => {
setQueueMetrics({...queueMetrics, [qName]:queueMetric}))
})
.catch((err) => console.error("ERR: unable to load queue ("+qName+") metrics: " + err))
})
}, [setQueueMetrics])
All the setQueueMetrics trigger correctly... however, when they do, it overwrites the value of the queueMetrics instead of what I want -- so when all is said, the last API call to come in is the value of queueMetrics
.
After quite a bit of looking, I changed the setQueueMetrics call to:
setQueueMetrics(Object.assign(queueMetrics, { [qName]: qMetric }))
This works on the intitial load of the component. BUT... on a secondary load, it does NOT work. The useEffect triggers as expected, the API calls go out as expected, and setQueueMetrics is called... but nothing updates.
These both feel like the wrong way to do it. I believe the second is working due to being by reference and thus getting around the context issues, but I'm not sure why it isn't working on subsequent loads of the component. It also feels less-than-good. So I'm wanting to know the best practice way of multiple async state updates of the same state object from a useEfect function.