Home > Back-end >  Accessing the updated state in useEffect doesn't work
Accessing the updated state in useEffect doesn't work

Time:05-13

I need to fetch two API-endpoints in the useEffectcall, where the second call uses the result of the first call.

So currently I have:

const [steamID, setSteamID] = React.useState<string>();
const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    setLoading(true);
    getLoggedInUser()
      .then((userObj) => userObj?.steamID)
      .then((fetchedSteamId) => {
        setSteamID(fetchedSteamId);
        console.log("steamID1: "   steamID);
        console.log("steamID2: "   fetchedSteamId);
      }).then(
         // second API-Call which needs steamID
         // by either using steamID(state) or fetchedSteamId(result)
      )
      .catch((err) => {
        setLoading(true);
      });
}, []);

I tried to append another .then() before the .catch() where I access the steamID state. But already with the code provided I have the following output:

steamID: undefined
steamID: 1234567891011

So when updating my state steamID inside useEffect, it will be undefined when accessed within useEffect unless i make any changes with hot-reload. The second output will always be correct.

I sure could just always pass the result further down, but is this the proper way? And how can I make sure, after useEffect, my state contains the correct values?

CodePudding user response:

You could always just pass fetchedSteamId to the next then in the promise chain and use that in whatever way you need:

const [steamID, setSteamID] = React.useState<string>();
const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    setLoading(true);
    getLoggedInUser()
      .then((userObj) => userObj?.steamID)
      .then((fetchedSteamId) => {
        setSteamID(fetchedSteamId);
        console.log("steamID1: "   steamID);
        console.log("steamID2: "   fetchedSteamId);
        return fetchedSteamId;
      }).then((fetchedSteamId) => {
        // use the id
        setLoading(false);
      })
      .catch((err) => {
        setLoading(false);
      });
}, []);

If the goal is to both set that id and use that id in another operation, it could work. Otherwise you can use another useEffect, with steamId as the dependency:

useEffect(() => {
    setLoading(true);
    getLoggedInUser()
      .then((userObj) => userObj?.steamID)
      .then((fetchedSteamId) => {
        setSteamID(fetchedSteamId);
        setLoading(false);
      }).catch(err => setLoading(false));
}, []);

useEffect(() => {
  // do some operation when steamId useState value changes
}, [steamId]);
  • Related