0

我的状态中有一个数组data,其中包含一组对象,但是当我尝试访问和呈现存储在对象中的一些信息时,页面上没有出现任何预期的文本。

我当前的代码在我的渲染函数中,如下所示:

<ul>
    {this.state.data.map(match =>
    <Link to={'teams/'+ team.homeId} key={match.id}><li>{match.homeTeam}</li></Link>
<ul>

当我检查控制台中的元素时,我看到undefined了我期望数据的位置。

await axios.get()该信息是在我的函数内部的请求中检索到的async componentDidMount(),这使我相信数据可能无法正确显示,因为在渲染发生时尚未检索到它,但是我不确定。

我之前曾尝试let match = this.state.data || {}在渲染开始时进行定义,以便一旦setState在我的 中发生渲染就会重新加载componentDidMount,但这不起作用。任何方向将不胜感激。

根据 MonteCristo 的要求进行编辑;

class Welcome extends Component {
    constructor(props) {
        super(props)
        this.state = {
            data: []
        }
    }


    async componentDidMount() {
        let res = await axios.get(`https://soccer.sportmonks.com/api/v2.0/livescores?api_token=${API}`)
        let matchInfo = new Array(res.data.data.length).fill().map(_ => ({}))

        res.data.data.forEach((id, i) => Object.assign(matchInfo[i], {id: id.id, homeScore: id.scores.localteam_score}, {awayScore: id.scores.visitorteam_score}))

        res.data.data.forEach((id, i) => {
            axios.get(`https://soccer.sportmonks.com/api/v2.0/teams/${id.localteam_id}?api_token=${API}`)
            .then(res1 => {
                Object.assign(matchInfo[i], {homeId: res1.data.data.id, homeTeam: res1.data.data.name})
            })
        })
        res.data.data.forEach((id, i) => {
            axios.get(`https://soccer.sportmonks.com/api/v2.0/teams/${id.visitorteam_id}?api_token=${API}`)
            .then(res2 => {
                Object.assign(matchInfo[i], {awayId: res2.data.data.id, awayTeam: res2.data.data.name})
            })
        })
        res.data.data.forEach((id, i) => {axios.get(`https://soccer.sportmonks.com/api/v2.0/leagues/${id.league_id}?api_token=${API}`)
            .then(res3 => {
                Object.assign(matchInfo[i], {leagueName: res3.data.data.name})
            })
        })
        this.setState({
            data: [...this.state.data, ...matchInfo]
        })
    }


    render() { 
        return ( 
            <div>
                <p className="text-xl font-semibold">Live Matches</p>
                <div>
                    <ul>
                        {this.state.data.map(match => 
                        <Link to={'teams/'+ match.homeId} key={match.id}><li>{match.homeTeam}</li></Link>)}
                    </ul>
                </div>
            </div>
         );
    }
}

export default Welcome;
4

3 回答 3

0

您需要像这样检查数据是否已成功检索:

<ul>
{this.state.data && this.state.data.map(match => {
return (<Link to={'teams/'+ team.homeId} key={match.id}>{match.homeTeam}</Link>)
}
 <ul>
于 2020-03-21T00:15:09.873 回答
0

您实际上需要等待请求完成。

你在this.setState({ data: [...this.state.data, ...matchInfo] })底部做 a ,但是你正在matchInfo异步地改变对象,所以在所有这些 axios 请求完成之前setState发生。变异状态不会导致重新渲染,只能通过.setState

如果您改为等待所有 axios 调用并在调用之前构建您的对象setState,您将获得所需的内容:

async componentDidMount() {
  const soccerApi = axios.create({
    baseURL: 'https://soccer.sportmonks.com/api/v2.0',
    params: { api_token: API }
  });
  const res = await soccerApi.get(`/livescores`);
  const matchInfo = await Promise.all(res.data.data.map(async row => {
    const [homeTeamInfo, awayTeamInfo, leagueInfo] = await Promise.all([
      soccerApi.get(`/teams/${row.localteam_id}`),
      soccerApi.get(`/teams/${row.visitorteam_id}`),
      soccerApi.get(`/leagues/${row.league_id}`)
    ]);
    return { 
      id: row.id,
      homeScore: row.scores.localteam_score,
      awayScore: row.scores.visitorteam_score,
      homeId: homeTeamInfo.data.data.id,
      homeTeam: homeTeamInfo.data.data.name,
      awayId: awayTeamInfo.data.data.id,
      awayTeam: awayTeamInfo.data.data.name,
      leagueName: leagueInfo.data.data.name
    };
  }));
  this.setState({
    data: [...this.state.data, ...matchInfo]
  });
}
于 2020-03-21T00:39:11.547 回答
0

主要问题是您在 forEach 中的 axios 调用。你不是在等他们。您在 forEach 中调用它们而不是等待。

所以你需要做这样的事情

const allPromises = res.data.data.map((id, i) => { return axios.get() } 

// then 

const allResponseValues = await axios.all(allPromises).catch(console.error)

// do something with allResponses and update matchInfo

// finally
this.setState({...})

还将您的渲染功能更新到下面以提高可读性和清晰度

            {this.state.data.map(match => (
              <Link to={"teams/" + match.homeId} key={match.id}>
                <li>{match.homeTeam}</li>
              </Link>
            ))}

于 2020-03-21T00:43:23.360 回答