i have a little problem with updating the UI in React after fetching additional data from the server. The problem is that not all products are updating the price in the UI. I´m sure its because of the async function. Heres my code:
useEffect(() => {
async function loadNotes() {
console.log("loading notes");
try {
setShowNotesLoadingError(false);
setNotesLoading(true);
const products = await ProductsApi.fetchProducts();
for (let index = 0; index < products.length; index++) {
const prices = await ProductsApi.getLowestPrice(products[index].asin);
products[index].lowestPriceFraction = prices.lastPriceFraction;
products[index].lowestPriceWhole = prices.lastPriceWhole;
setProducts(products);
}
setProducts(products);
} catch (error) {
console.error("Fehler: " + error);
setShowNotesLoadingError(true);
} finally {
setNotesLoading(false);
}
}
loadNotes();
}, []);
Hope someone can help my to fix my little problem. Thank you
2
Answers
The problem is that these lines are mutating the array, and that array is in state (after the first loop anyway). Mutating state causes problems, because react expects it can to an
===
comparison between the old and new state to tell if it has changed. So when you callsetProducts(products)
react does its===
, sees that it’s the same array, and thus skips every render but the first.Instead, every time you set state you must do so without mutation. In your case that means making a copy of the array, and making a copy of the specific item you want to change
Btw, one way you could change this code is to get all the prices in parallel (thus reducing the total loading time) and just set state once at the end (thus simplifying the code):
The issue you’re facing is related to how you’re updating the state inside the loop. Since React state updates are asynchronous, you might be experiencing unexpected behavior due to the loop running faster than the state updates. To fix this, you should accumulate the updated products in a separate array and then update the state once, outside of the loop.
Here’s how you can modify your code to ensure proper updating of the UI after fetching and updating the product prices:
In this code, I’ve created a new array
updatedProducts
where I accumulate the products with updated price information. After the loop, I update the state with this array using a singlesetProducts
call. This ensures that the UI will be updated with all the correct price information once the state is updated.