Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling the setState hook within an async function

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

like image 209
codean Avatar asked Nov 14 '25 23:11

codean


1 Answers

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();
}, []);
like image 65
Zachiah Avatar answered Nov 17 '25 11:11

Zachiah



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!