Реакция: невозможно отобразить карту состояния выборки - PullRequest
0 голосов
/ 05 марта 2020

Итак, вот моя проблема: я получаю API, вот действие:

const OPTIONS = {
  method: 'GET',
  headers: {
    'X-RapidAPI-Host': 'api-football-v1.p.rapidapi.com',
    'X-RapidAPI-Key': '44316d2130msh21fed66e06e6a24p1dd597jsnf2e92ca6ac85'
  }
};

export function setLeagues() {

  const countries =
    [
      {
        france: ["Ligue 1", "Ligue 2"]
      },
      {
        england: ["Premier League"]
      },
      {
        germany: ["Bundesliga 1"]
      }
    ];

  let leagues = [];

  countries.forEach((country) => {
    fetch(`https://api-football-v1.p.rapidapi.com/v2/leagues/current/${Object.keys(country)[0]}`, OPTIONS)
    .then(response => response.json())
    .then((data) => {
      Object.values(country)[0].forEach((league) => {
        data.api.leagues.filter((league_api) => {
          if(league_api.name === league) {
            leagues.push(league_api);
          }
        });
      });
    });
  });
  return {
    type: 'SET_LEAGUES',
    payload: leagues
  };
}

Лиги возвращают правильный массив объекта лиги. Вот редуктор:

export default function(state, action) {
  if (state === undefined) {
    return [];
  }

  if (action.type === 'SET_LEAGUES') {
    return action.payload;
  } else {
    return state;
  }
}

И, наконец, мой контейнер:

class LeaguesLabel extends Component {

  componentDidMount() {
    this.props.setLeagues()
  }

  render() {
    console.log(this.props.leagues);
    return(
      <div>
        <ul>
          {
            this.props.leagues.map((league) => {
              return(
                  <li>
                    {league.name}
                  </li>
              );
            })
          }
        </ul>
      </div>
    );
  }
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(
    { setLeagues: setLeagues },
    dispatch
  );
}

function mapStateToProps(state) {
  return {
    leagues: state.leagues
  }
}


export default connect(mapStateToProps, mapDispatchToProps)(LeaguesLabel);

Конечно, я импортирую setLeague в этот контейнер.

Ничего не отображается, пока моя консоль. В журнале (this.props.leagues) отображается хороший массив объектов, содержащих «лигу».

Заранее благодарю за помощь!

Ответы [ 2 ]

0 голосов
/ 05 марта 2020

Другой ответ верен, но если продолжить, подумайте о вашей функции следующим образом:

Сначала он обрабатывает этот блок, поэтому он перебирает страны и начинает выполнять запросы на выборку:

countries.forEach((country) => {
    fetch(`https://api-football-v1.p.rapidapi.com/v2/leagues/current/${Object.keys(country)[0]}`, OPTIONS)
    .then(response => response.json())
    .then((data) => {
      Object.values(country)[0].forEach((league) => {
        data.api.leagues.filter((league_api) => {
          if(league_api.name === league) {
            leagues.push(league_api);
          }
        });
      });
    });
  });

Далее, до того, как предыдущая работа успела что-либо сделать, он обработает следующий блок:

  return {
    type: 'SET_LEAGUES',
    payload: leagues
  };

Итак, он начал запускать countries.forEach, но обещания выборки разрешаются за пределами этой функции, поэтому, прежде чем какие-либо данные будут помещены в ваш массив, вы уже возвращаете их.

Попробуйте использовать синтаксис await/async, так вам будет гораздо легче справиться с попытками спорить обещания, что-то вроде:

export async function setLeagues() {
  const countries = [
    {
      name: "france",
      leagues: ["Ligue 1", "Ligue 2"],
    },
    {
      name: "england",
      leagues: ["Premier League"],
    },
    {
      name: "germany",
      leagues: ["Bundesliga 1"],
    },
  ]

  let payload = []

  for (const country of countries) {
    const { name, leagues } = country
    const response = await fetch(
      `https://api-football-v1.p.rapidapi.com/v2/leagues/current/${name}`,
      OPTIONS
    )
    const data = await response.json()

    for (const apiLeague of data.api.leagues) {
      if (leagues.includes(apiLeague.name)) {
        payload.push(apiLeague)
      }
    }
  }
  return {
    type: "SET_LEAGUES",
    payload,
  }
}
0 голосов
/ 05 марта 2020

Проблема в том, что вы вызываете асинхронную функцию и возвращаете свой результат за пределы ее периметра.

Что происходит при вызове оператора return до получения ответа на вызов API.

Следовательно, список будет пустым ...

Вы должны прочитать об асинхронных функциях здесь https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

Кроме того, чтобы использовать asyn c функционирует в редукционных действиях, вы должны использовать redux thunk.

Хороший пример здесь -> https://appdividend.com/2018/10/03/redux-thunk-tutorial-example/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...