Search code examples
javascriptpromisefetch-api

fetch inside of then() doesn't work the first time onClick()


So I am trying to make a form that when it is submitted this code is called.

async function addListing() {
        let listing: any = {
            make: make,
            model: model,
            year: year,
            mileage: mileage,
            price: price
        };

        await fetch("http://localhost:8080/api/listing", {
            method: "POST", 
            headers: {"Content-type": "application/json"},
            body: JSON.stringify(listing)
        })
        .then(() => {
            fetch("http://localhost:8080/api/listing")
            .then(res => res.json())
            .then(data => {
                setListingID(data[data.length - 1].id);
            })
            .catch(error => {
                console.log(error);
            });
        })
        .then(() => {
            console.log("Listing: ", listingId, " Seller: ", sellerId)
        })
        .catch(error => {
            console.log(error)
        })
    }

The post function works fine however the get function inside the first then() doesn't work the first time the button it is clicked. So the first time I click on the submit button I get: "Listing: Seller: 3" And the second time (and each time after that) it is correct for example: "Listing: 123 Seller: 3"

I tried all of yesterday to find a solution I made a separate function and it wasn't working Today I searched up the whole internet tried a bunch of things but I can't seem to find what I did wrong.

When I get this to work I want to use that listingId function in order to call another function which will connect the listingId and sellerId in a separate table.


Solution

  • You've made a false assumption in your debugging. The .then() callback in question is invoking an asynchronous operation, but nothing ever awaits that operation. So it's immediately moving to the next .then() in the chain.

    Return the Promise:

    .then(() => {
      return fetch("http://localhost:8080/api/listing")
         .then(/* etc... */);
    })
    

    Taking a step back... Mixing await and .then() callbacks is a recipe for confusion. Since you're using async/await, why not use async/await? For example:

    try {
      await fetch("http://localhost:8080/api/listing", {
        method: "POST", 
        headers: {"Content-type": "application/json"},
        body: JSON.stringify(listing)
      });
      const res = await fetch("http://localhost:8080/api/listing");
      const data = await res.json();
      setListingID(data[data.length - 1].id);
      console.log("Listing: ", listingId, " Seller: ", sellerId);
    } catch (error) {
      console.log(error)
    }
    

    Additionally...

    Is this React?:

    setListingID(data[data.length - 1].id);
    

    If so, please see The useState set method is not reflecting a change immediately

    State updates are asynchronous (and not awaitable). If you need that value immediately after invoking a state update, store it in a variable. For example:

    const data = await res.json();
    const newListingID = data[data.length - 1].id;
    setListingID(newListingID);
    console.log("Listing: ", newListingID, " Seller: ", sellerId);