0

I apologize if a similar issue was asked elsewhere, as I didn't even really know how to ask this question or what to look for since I haven't really come across anything like this before.

So I will try to make this simple, I am making a fetch call (GET) from my frontend ReactJS webapp to my Java Spring API that sits on top of a MySQL database. I am setting an array to the return value of the fetch call since the return value is an array of objects (a list of "groups" if you care). I am using async await on the function which is being called within the componentDidMount lifecycle event.

Essentially what is happening that I cannot figure out is that, although in the Network tab I can clearly see that only one "group" object is being returned, in the array it shows two when I console log it. Whats even weirder is that in the second .then() callback when I console log JSON.parse(text) it shows what I would expect to be returned - a single "group" object. But then when I assign my groups variable to JSON.parse(text), then it shows two "group" objects instead of just the one I am expecting. One thing I have done is moved the fetch call out of the getGroups() function and placed it directly in componentDidMount() and then it worked fine. This leads me to believe that I am screwing something up with how async await should be setup. I also change var groups to const groups (obviously had to directly assign const groups to the response, so it was limited to the scope of the .then() callback) and that also gave me the expected result.

I have another function called searchGroups() where I am having the same exact problem with the same exact endpoint. I'll post some code below. If theres anything else you need to see please just let me know.

Would really appreciate some help here, been working at figuring this out for a couple days now... otherwise I might have to go Spider Man III Tobey Maguire dark spidey on this thing.

async componentDidMount(){ 
    await this.getGroups();
}

//<Some other lifecycle events here...>

async getGroups(){
    var ownerID = localStorage.getItem("userID");
    var groups = [];
    var sharedGroups = [];
    
    await fetch(baseURI + "/api/group/forOwner/" + ownerID, {  
        method: "GET",                          
        headers: {"Content-Type": "application/json",
                  "Authorization": "Bearer " + localStorage.getItem("auth_token")}
    })
    .then(res => res.text())
    .then(
        (text) => {
            var result = text.length ? JSON.parse(text) : {};
            groups = result;
        }
    ).catch(console.log);

    await fetch(baseURI + "/api/group/forTeacher/" + ownerID, {  
        method: "GET",                          
        headers: {"Content-Type": "application/json",
                  "Authorization": "Bearer " + localStorage.getItem("auth_token")}
    })
    .then(res => res.text())
    .then(
        (text) => {
            var result = text.length ? JSON.parse(text) : {};
            sharedGroups = result;
            console.log(sharedGroups);
        }
    ).catch(console.log);

    if(groups.length === undefined){
        groups = [];
    }

    if(sharedGroups.length === undefined){
        sharedGroups = [];
    }

    this.setState({
        ownerGroups: groups,
        sharedGroups: sharedGroups
    });
}

 //<Some more functions here...>

 async searchGroups(){

    document.getElementsByClassName("loaderBackground")[0].style.display = "flex";

    var list = document.getElementById("groupList-Admin");
    var count = 0;
    var searchText = document.getElementsByClassName("Fit4Life-Searchbar-Admin")[0].value.trim();
    var ownerID = localStorage.getItem("userID");

    var groups = [];
    var sharedGroups = [];

    while (list.firstChild) {
        list.removeChild(list.lastChild);
    }

    await fetch(baseURI + "/api/group/forOwner/" + ownerID, {  
            method: "GET",                          
            headers: {"Content-Type": "application/json",
                      "Authorization": "Bearer " + localStorage.getItem("auth_token")}
        })
        .then(res => res.text())
        .then(
            (text) => {
                groups = text.length ? JSON.parse(text) : {};
            }
        ).catch(console.log);

        await fetch(baseURI + "/api/group/forTeacher/" + ownerID, {  
            method: "GET",                          
            headers: {"Content-Type": "application/json",
                      "Authorization": "Bearer " + localStorage.getItem("auth_token")}
        })
        .then(res => res.text())
        .then(
            (text) => {
                var result = text.length ? JSON.parse(text) : {};
                sharedGroups = result;
            }
        ).catch(console.log);

     //<Rest of searchGroups() function and class code...>

response according to console.log: console.log response

response according to network tab: network tab response

  • I don't trust the "preview" tab. What's on the actual response tab? – Garr Godfrey Sep 14 '21 at 02:39
  • @GarrGodfrey It shows the same, but just in case you want to see it here is the full response tab (some sensitive data I set to ""): >>> [{"group_id":27,"title":"Group 1","group_owner":{"user_id":35,"first_name":"Timmy","last_name":"Turner","display_name":"T_Turn","email":"Turner@gmail.com","weight":0.0,"height_feet":0,"squat_max":0,"deadlift_max":0,"bench_max":0,"hang_clean_max":0,"height_inches":0,"access_type":"ADMIN","classrooms":[]}}] – wymtowne Sep 14 '21 at 02:53
  • 1
    It means that some code - other than the one you've shown - accidentally *mutates* the state array by pushing another group into it. The fetch code is not to blame. If you look closely at the log output, it logs an array containing a single object in the preview - only once you expand the live state of the array, you see the second element. You can also do `console.log(sharedGroups.length);` instead of `console.log(sharedGroups);` to verify - you'll get `1` there. – Bergi Sep 14 '21 at 02:54
  • @Bergi so question - by using await, doesn't that pause execution until the fetch call completes? And if so, does that include the .then callbacks? Or after the initial GET request is returned, does execution continue even if code in the .then callbacks is still executing? – wymtowne Sep 14 '21 at 02:57
  • @wymtowne `await` pauses the execution of the current `async function` until the promise is settled. Doesn't matter how that promise was created (e.g. as the return value from a `.then()` call). But nothing of this seems related to your problem. – Bergi Sep 14 '21 at 02:59
  • @Bergi right absolutely, was just curious. Thanks for putting me on the right path! – wymtowne Sep 14 '21 at 03:26
  • 1
    @Bergi Just wanted to follow up, you were absolutely right. I was appending another array to groups via groups.push.apply() in another function call and it was causing the unexpected behavior. Thank you, wish I could upvote and accept a comment. – wymtowne Sep 14 '21 at 22:26

0 Answers0