What's up friends,
I have a problem. I have DOM elements that show data from the variable (useState) that I am saving with some "accounts".
I have a function that updates the data of each element by calling the api, and I have a function that refreshes all the elements one by one, the problem is that when using the function that refreshes all the elements, the changes are not reflected correctly in the dom but when using the function individually (I have a button for that) I can see the changes correctly reflected.
I do not get the error, if you can help me I would be very grateful.
Refresh Function
let [accounts, setAccounts] = useState
const refreshAccount = async (id, name, token) => {
await setIsBusy(true)
await updateWorkingStatus(id, true, name, token)
let work = await axios.get(
'http://192.168.0.101:3000/account/refresh/' + id,
)
await updateWorkingStatus(id, false, name, token)
await setIsBusy(false)
// console.log(work.data.result)
let accs = [...accounts]
let index = accs.findIndex((acc) => acc._id === id)
accs[index] = work.data.result
accs[index]._id = id
// console.log(accs[index])
setTimeout(() => {
setAccounts(accs)
}, 0)
return 'OK'
}
Refresh Selected Item (I already have a function that selects each item and works nice)
const refreshSelected = async () => {
let finalAccounts = await accounts.filter((acc) => acc.selected)
for (let i = 0; i < finalAccounts.length; i++) {
await refreshAccount(
finalAccounts[i]._id,
finalAccounts[i].name,
finalAccounts[i].token,
)
}
}
I know the problem is updating the status, but I can't solve it. Implement a setTimeout and the previous element to the last is updated or the last of the cycle, the previous ones are left with the outdated data (first state).
I think problem is when using FOR loop on React, but dont know how to use it correctly
The problem is probably that the setAccounts function is asynchronous, but the execution doesn't wait for it to complete. Because setAccounts is asynchronous, subsequent calls in the same update cycle will overwrite previous updates, and the previous changes will be lost, causing only the last update to take effect.
You could store the changes to an array and update it after all the API requests have finished.
let [accounts, setAccounts] = useState
const refreshAccount = async (id, name, token) => {
await setIsBusy(true)
await updateWorkingStatus(id, true, name, token)
let work = await axios.get(
'http://192.168.0.101:3000/account/refresh/' + id,
)
await updateWorkingStatus(id, false, name, token)
await setIsBusy(false)
// console.log(work.data.result)
let accs = [...accounts]
let index = accs.findIndex((acc) => acc._id === id)
accs[index] = work.data.result
accs[index]._id = id
return accs
}
const refreshSelected = async () => {
let finalAccounts = await accounts.filter((acc) => acc.selected)
let newAccounts = []
for (let i = 0; i < finalAccounts.length; i++) {
const accs = await refreshAccount(
finalAccounts[i]._id,
finalAccounts[i].name,
finalAccounts[i].token,
)
newAccounts = newAccounts.concat(accs)
}
setAccounts(newAccounts)
}