Im learning about how to call REST APIs from React and am confused about what happens when we call React within an async function. In my component below, we see that in the first line of fetchPlaces function, we are calling the setIsFetching() state to be true.
import { useState, useEffect } from "react";
import Places from "./Places.jsx";
import Error from "./Error.jsx";
import { sortPlacesByDistance } from "../loc.js";
import { fetchAvailablePlaces } from "../http.js";
export default function AvailablePlaces({ onSelectPlace }) {
const [isFetching, setIsFetching] = useState(false);
const [availablePlaces, setAvailablePlaces] = useState([]);
const [error, setError] = useState();
useEffect(() => {
async function fetchPlaces() {
setIsFetching(true);
try {
const availablePlaces = await fetchAvailablePlaces();
setAvailablePlaces(sortedPlaces);
setIsFetching(false);
});
} catch (error) {
setError({
message:
error.message || "Could not fetch places, please try again later.",
});
setIsFething(false);
}
}
fetchPlaces();
}, []);
if (error) {
return <Error title="An error occurred!" message={error.message} />;
}
return (
<Places
title="Available Places"
places={availablePlaces}
isLoading={isFetching}
loadingText="Fetching place data..."
fallbackText="No places available."
onSelectPlace={onSelectPlace}
/>
);
}
My question here is does React wait for the state to be updated until the whole function is completed? Or does it go and update the state then since its an async function and rerender the component again? If so, why?
Im guess Im confused because in other functions say for example:
function a() {
setIsFetching(true)
// .... a lot more logic is done below
}
doesn't React wait until after a is done running to update the state and re-render the component? Why is it with the async function that the state is being updated before the function is running? I would think it would wait for the whole function to execute since we have the await keyword
React will wait until your code yields control to the JS event loop before updating. Basically:
async function fetchPlaces() {
// no updates yet
setIsFetching(true);
// update is batched to be ran on the next rerender
try {
// by using `await` you are yielding control to the JS event loop.
// code in this block will not run any more until `fetchAvailablePlaces` resolves.
const availablePlaces = await fetchAvailablePlaces();
// by here react will have updated the DOM
setAvailablePlaces(sortedPlaces);
// update is batched from the previous line
setIsFetching(false);
// this gets added to the batch
});
} catch (error) {
setError({
message:
error.message || "Could not fetch places, please try again later.",
});
setIsFething(false);
}
}
fetchPlaces();
}, []);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With