反应:无法呈现获取状态的地图

时间:2020-03-05 15:07:35

标签: javascript reactjs redux

这是我的问题: 我获取一个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导入到此容器中。

当我的console.log(this.props.leagues)显示一个包含“联盟”的对象的良好数组时,什么也没有显示。

预先感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

问题是您正在调用异步函数,并在其范围之外返回结果。

这是怎么回事,在收到API调用的答案之前先调用return语句。

因此,列表将为空...

您应该在https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

处了解异步功能。

最重要的是,为了在redux动作中使用异步功能,您应该使用redux thunk。

这里很好的例子-> https://appdividend.com/2018/10/03/redux-thunk-tutorial-example/

答案 1 :(得分:0)

另一个答案是正确的,但要对此进行扩展,请考虑这样的功能

首先,它处理此块,然后遍历各个国家并开始执行提取请求:

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,
  }
}