0

So I have to make two api calls in my app. The first one is a POST request that creates a new game model. The second one is a GET request that uses a value from the first request. I tried to write a function so that it could all be invoked sequentially. However it seems like it's not working properly :(

Function and used states

  const dateTime = new Date().toJSON();
  const [code, setNewCode] = useState("");
  const [gameData, setGameData] = useState<any[]>([]);

  useEffect(() => {
    const asyncFunction = async () => {
      try {
        const firstResponse = await axios
          .post(apiUrl + "/games", {
            game: {
              name: dateTime,
            },
          })
          .then(function (response) {
            console.log(response.data.code);
            setNewCode(response.data.code);
          })
          .catch(function (error) {
            console.log(error);
          })
          .finally(() => {
            console.log(code);
          });
        const thirdResponse = await axios
          .get(apiUrl + "/games/" + code)
          .then(({ data }) => {
            console.log(JSON.stringify(data));
            let newData = JSON.stringify(data);
            setGameData(newData);
          })
          .catch((error) => console.error(error))
          .finally();
        console.log("Get is done");
      } catch (error) {
        return error;
      }
    };
    asyncFunction();
  }, []);

And here is the log that I get in console:

LOG ST231 // code that is taken from json.response from POST request
LOG       // somehow empty value of code state that should've been updated by the POST request
LOG {"id":6,"name":"2023-02-28T12:55:01.221Z","code":"BX892","fight":false,"turn":0,"created_at":"2023-02-28T12:55:01.326Z","updated_at":"2023-02-28T12:55:01.326Z","user_id":1,"status":"active","players":[],"monsters":[]} // response from GET request. Why is the code "BX892"? Where did is take it? How is it possible?
  • okay.. - try first to not mix .then().catch()-chains with async wait blocks, as both basically do the same and you should use once concept not both. https://javascript.info/promise-chaining - if it does not work still post again – Fapi Feb 28 '23 at 21:10

1 Answers1

0

Some issues here:

  1. Setting state does not happen immediately. See the link for more on why your state would log an old value right after being set.

  2. You're not returning anything from your chained calls - the .finally would have to return something for the variable to get populated.

  3. Try to avoid mixing await and .then. It can be harder to read and reason about.

If all you need code for is making the 2nd API call, you don't need to store it in state; it can stay inside your useEffect function. Ex:

  const dateTime = new Date().toJSON();
  const [gameData, setGameData] = useState<any[]>([]);

  useEffect(() => {
    const asyncFunction = async () => {
      try {
        // removed .then/.catch blocks - if there's an error,
        // it will be caught by the outer try/catch.  This ensures
        // firstResponse will be populated when the next call is made,
        // and setGameDate won't be called if there's an error there
        const firstResponse = await axios
          .post(apiUrl + "/games", {
            game: {
              name: dateTime,
            },
          });
        const thirdResponse = await axios
          .get(apiUrl + "/games/" + firstResponse.data.code);
        const newData = JSON.stringify(thirdResponse.data);
        setGameData(newData);
        console.log("Get is done");
      } catch (error) {
        console.log(error);
        return error;
      }
    };
    asyncFunction();
  }, []);
Abe
  • 4,500
  • 2
  • 11
  • 25