0

I have been having an issue with a React webapp I'm building. Because of the way the API is structured, I need to do multiple API calls to get the stats data for a searched NBA player. The first API call fetches a list of players who meet the search criteria (i.e. when you search the name "Williams" it will display a list of player IDs which you can then do another API call with for more detailed stats on the chosen player). I am having trouble rendering a list of radio buttons with names of all the players who match the search criteria: there is a delay in rendering this list - I need to do another action (i.e. a backspace or writing another character) for the list to display properly, similar to this post here: React not rendering search results from API onChange

The answer in this case says that the async/await is handled incorrectly, but I can't see the problem in my handling of the API calls.

async function findListofPlayers(searchParams) {
let playerCall = await fetch(`https://www.balldontlie.io/api/v1/players?search=${searchParams}&per_page=5`)
let playersList = await playerCall.json();
let playersArray = []
for (let i = 0; i < playersList.data.length; i++) {
  playersArray.push(playersList.data[i].id)}
return playersArray}



async function submitHandler(event) {
event.preventDefault()
let currentSearch = [];
const playersArray = await (findListofPlayers(searchParams))
playersArray.forEach( async (player) => 
    {let entry = await fetch(`https://www.balldontlie.io/api/v1/players/${player}`)
    let result = await entry.json();
    currentSearch.push(result)
    })
toggleSubmitted(true)
updateSearchedPlayers(currentSearch)}

Above you see the two functions involved in retrieving a list of players who match a search criteria, ending in a returning of a list of 5 players who match the criteria. From here, the list gets passed as a prop to this functional component which renders buttons from the list the API returns:

export default function Results(props) {

const [playerList, setPlayerList] = React.useState([])
React.useEffect(() => setPlayerList(props.searchedPlayers), [props.searchedPlayers])

const playerButtons = playerList.map(x => 
    <div key={x.id}>
        <input 
            type="radio"
            name="playerChoose"
            onChange={props.selectPlayer}
            value={x.id}
            alt={`${x.first_name} ${x.last_name}`}>
        </input>
        <label>
            {`${x.first_name} ` + x.last_name}
        </label>
    </div>)

return <div className="results">
    <form onSubmit={props.selectPlayer} className="searchResults">
        <label htmlFor="year">Season: </label>
        <select 
            name="year"
            defaultValue={currentSeason}
            onChange={props.selectYear}>
            {seasonDropdown}
        </select>
        <br></br><br></br>
        <div className="playerList">
            <div>
                {playerButtons}
            </div>
        </div>
    </form>
    <br></br>
    <div className="disclaimer"><b>Search results are limited to 5 players.</b></div>
    <button onClick={props.selectPlayer}>Find Player Stats</button>
</div>
}

From my perspective, I'm awaiting the API calls to complete before moving on. In the submitHandler, there is a function which sets the state of "submitted" to true, but only after the asynchronous functions are completed (because I am awaiting them, right?), and when submitted is true that is when the radio button component will render. But that isn't the behaviour I'm getting. I'm a little confused on where to go from here - I've even tried moving the playerList state to the radio button rendering component instead of strictly passing the playerList as a prop, but that didn't do anything. Any help would be appreciated.

  • Using `await` inside a forEach loop won't work like you expect. The loop finishes long before the await calls. Use Promise.all() instead. – ChrisG May 25 '22 at 23:27

0 Answers0