Search code examples
reactjsasync-awaitfetchuse-effectarray.prototype.map

How to implement API call to server and display data on button click (React, Node, Express)


EDIT: I've debugged and provided an answer to some of my issues below.

I've been researching this issue for a while now and can't seem to find an adequate resolution. As you will see looking at my code, I have a lot to learn. The issue seems to come from trying to display data that hasn't finished fetching despite my redundant placement of await. I am also curious if I should place my getData() function within a useEffect hook? The problem with this is I use the getData() function in my submit button's onClick. So when I run my app, getData() is only available in useEffect's scope.

  const getData = async () => {
    if(searchData.platform !== "" && searchData.platformUserIdentifier !== ""){
      setValidInput(true);
      const response = await fetch(`http://localhost:8080/data?platform=${searchData.platform}&username=${searchData.platformUserIdentifier}`);
      const json = await response.json();
      await finishAllOperations(json)
    } else {
      setValidInput(false);
    }
  }
  
  function finishAllOperations(json) {
  if(json.code === "ERR_BAD_REQUEST"){
    console.log(`Request failed with a status code ${json.status}`);
    setErrorMessage(true);
    setDisplayTable(false);
  } else {
    console.log("Request successful");
    setMatches(json);
    setErrorMessage(false);
    setDisplayTable(true)
  }
}

const displayMatchRows = matches.map((match,index) => {

  //dummy data to populate if reward is available
  function checkRewardAvailability(match){
    const value = Math.random()
    if (value <= .5) {
      return true
    } else {
      return false
    }
  }

  return (
    <tr key={match.id}>
      <td>{index+1}</td>
      <td>{parseDate(match.metadata.endDate.value)}</td>
      <td>{match.stats.kills.value}</td>
      <td>{match.stats.rankScore.value}</td>
      <td>{checkRewardAvailability()?<button className="reward-button">Claim Reward</button>:""}</td>
    </tr>
  )
})

When I go to deploy my code to my Node server and attempt to submit an API call with the above code I receive the following error:

TypeError: b.map is not a function

Furthermore, when I run my program with my client and server running on separate terminals my code does work and the data does properly get displayed. However, the "Request successful" console log occurs before the fetch has finished running. Obviously, I would like for the "Request successful" (see attached screenshot) to occur after I have completely finished fetching all data.

"Request Success" before fetch finish

I really appreciate any input as on I'm the verge of smashing my computer. Thank you in advance.


Solution

  • I am happy to report after several hours of debugging, the error came from my .env file providing an undefined value because it was not getting moved alongside my package.json file.

    Because the .env file was in the wrong place, I was not getting returned an array that .map would work on. Once I realized the error I was receiving had something to do with my server's API call, I was getting an error that went

    {"code":"ERR_HTTP_INVALID_HEADER_VALUE"}

    This seemed very vague to me and took a while to locate. If you're receiving this error and you are using a .env file, check to be sure it's not returning an undefined value. If it is undefined, then ensure that the .env files is in the same directory as your package.json file.