Search code examples
javascriptreactjsreduxgetcodesandbox

React - Populating First Select Option with Redux State


I have component League.js where there are 4 boxes containing League team details.

The team details are coming from this API => https://www.api-football.com/demo/api/v2/teams/league/${id}

When I click on each of the league boxes I am populating the Dropdown in my component Details.js

I won't get the team_id of the first team in the dropdown anytime I click on each of the League boxes in League.js in order to have the right calculation in a component called Stat.js. To do this I make a call request to this endpoint => https://www.api-football.com/demo/api/v2/statistics/${league}/${team}

So I need to pass league_id and team_id as a parameter, I can get both values correctly but I am doing something wrong on how to pass the first team_id of the team for each league.

These are the steps, I put only the relevant code. I am creating firstTeamStats state that I am dispatching

In my actions => index.js

export const RECEIVE_FIRST_TEAM_STATS = "RECEIVE_FIRST_TEAM_STATS";

export const receivedFirstTeamStats = json => ({
  type: RECEIVE_FIRST_TEAM_STATS,
  json: json
});



.get(`https://www.api-football.com/demo/api/v2/teams/league/${id}`)
.then(res => {
  let teams = res.data.api.teams;
  dispatch(receivedFirstTeamStats(teams[0].team_id));
})

in my reducer => index.js

case RECEIVE_FIRST_TEAM_STATS:
  return {
    ...state,
    firstTeamStats: action.json,
    isTeamsDetailLoading: false
  };

in my League.js component

import {getTeamsStats} from "../actions";

const mapStateToProps = state => ({
  firstTeamStats: state.firstTeamStats
});

const mapDispatchToProps = {
  getStats: getTeamsStats,
};

const onClick = (evt, id, firstTeamStats) => {
  evt.preventDefault();
  getDetail(id); \\  get the team names in the Detail.js component
  getStats(id, firstTeamStats); \\ get the state value for the first team in the dropdown in Detail.js component
};

<a href={`#${item.league_id}`} onClick={(e) => onClick(e, item.league_id, firstTeamStats)}

Right now firstTeamStats in the onclick method above returns correctly the first team state value but of the existing league and not in the one where I click which is what I want.

However I can get this correctly in the Details.js Component, I have put {firstTeamStats} there in the demo where I have reproduced my case => https://codesandbox.io/s/romantic-solomon-6e0sb (Use CORS Unblock Chrome extension to see )

So the question is, how can i pass {firstTeamStats} correctly in League.js in the method onclick to the request getStats(id, firstTeamStats) where {firstTeamStats} is the state of my first team_id of the league?


Solution

  • Whenever you are making an API call, it is an asynchronous event. You should always await, before using its response in the next line.

    So inside getDetail(), you are making an API call. But you haven't declared this method as async. so you are not waiting for it to complete and in the next line you are calling getStats() method with an old data. Thats why your app will always be a step behind, than your DOM events.

    • One way would be to use async|await and return the API response from the function, instead of using dispatch.

    • You can also invoke the getTeamsStats() inside the getTeamsDetailById() after the api response is fetched, instead of invoking it inside OnClick() event.

    const onClick = (evt, id, firstTeamStats) => { evt.preventDefault(); getDetail(id); \\ this is an async api call. you should have used await here. getStats(id, firstTeamStats); \\ It will execute before the new stats are fetched };

    In Stats.js, you should not be strictly validating these fields to show Statistics... these are only numbers.. can also be 0 at times. so please remove these checks.

    if (
         teamsStatsWinHome &&
         teamsStatsWinAway &&
         teamsStatsDrawHome &&
         teamsStatsDrawAway &&
         teamsStatsLoseHome &&
         teamsStatsLoseAway
       ) {
    

    I have a working instance of your application... check below. https://codesandbox.io/s/charming-dewdney-zke2t

    Let me know, if you need anything.