React:如何获取多个API

时间:2019-09-25 18:40:05

标签: javascript reactjs

实时代码为here

使用NHL APi,尝试制作一个仅显示每个玩家信息的React应用。该代码现在可以正常工作(返回常规花名册信息和一个特定球员的数据),但是我想显示团队的所有球员信息。不只是一个。

我是使用多个API的新手,大约有47位玩家。我真的必须单独获取每个播放器,进行47个API调用吗?

还是有更好的方法?想知道我是否能够一次获取名册API,然后以某种方式从那里显示所有个人玩家的信息。

任何帮助将不胜感激!

import React, { Component } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends Component {
  state = {
    loading: true,
    roster: null,
    spezza: null
  };

  // Always fetch here

  async componentDidMount() {
    // Roster
    const api = "https://statsapi.web.nhl.com/api/v1/teams/10/roster";
    const response = await fetch(api);
    const data = await response.json();

    console.log(data.roster[0]);

    // Spezza
    const apiSpezza = "https://statsapi.web.nhl.com/api/v1/people/8469455";
    const responseSpezza = await fetch(apiSpezza);
    const dataSpezza = await responseSpezza.json();

    console.log(dataSpezza.people[0]);

    // When the component mounts, set the new state values based on the API
    this.setState({
      loading: false,
      roster: data.roster[0],
      spezza: dataSpezza.people[0]
    });
  }

  render() {
    return (
      <div className="App">
        {/* If loading = true - meaning we can't fetch the API, then display loading.
        If loading value = false, meaning we fetched it, display the values from the API */}
        {this.state.loading ? (
          <div>loading...</div>
        ) : (
          <>
            <h1>Roster:</h1>
            <p>Jersey Number: {this.state.roster.jerseyNumber}</p>
            <p>Full Name: {this.state.roster.person.fullName}</p>
            <h1>Spezza:</h1>
            <p>Jersey Number: {this.state.spezza.primaryNumber}</p>
            <p>Age: {this.state.spezza.currentAge}</p>
            <p>Height: {this.state.spezza.height}</p>
            <p>Weight: {this.state.spezza.weight} lbs</p>
            <p>Nationalty: {this.state.spezza.nationality}</p>
          </>
        )}
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

5 个答案:

答案 0 :(得分:0)

因此,在查看documentation that I could find on the NHL API时,似乎并没有像他们对团队所做的那样,他们可以在一个请求中调用多个用户的统计信息。

我的建议是对请求执行Promise.all()或至少将您的等待移至使用数据的位置,以便所有请求可以立即触发,然后等待所有请求回来。就目前而言,您正在发出第一个请求,等待它回来,然后发出下一个请求。

答案 1 :(得分:0)

如果API没有接受路由,例如说一个玩家ID的数组并返回所有填充的详细信息,那么是的,您将需要单独进行所有调用。使用axios作为建议的注释者之一或使用本机Fetch API使用Promise.all,可以使用多种方法来实现此目的,但是重复这么多网络请求可能会给页面增加明显的加载时间。

答案 2 :(得分:0)

Promise.all([
    fetch(apiSpezza),
    fetch(api),
  ]).then(([data1, data2]) => {
cosnole.log(data1,data2);
})

我建议使用本地主机调用API,并且不要直接传递API URL。

答案 3 :(得分:0)

Promise.allSettled比Promise.all更好。与Promise.all的不同之处在于,它不会仅因为单个调用失败而失败。这是一个新的api,因此,如果您完全关心广泛的支持,则需要对其进行填充。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled

类似的东西:

const results = await Promise.allSettled(fetch(data.roster.map(player => 'https://statsapi.web.nhl.com/api/v1/people/${player.id}')));
const people = await results.filter(p => p.status === 'fulfilled').map(p => p.json());

答案 4 :(得分:0)

很抱歉,答案很长,但是我相信这是正确的方法

我将列表和列表项划分为2个单独的组件。

保留您喜欢的组件,就像剪下调用Spezza的部分一样

...
// Spezza
const apiSpezza = "https://statsapi.web.nhl.com/api/v1/people/8469455";
const responseSpezza = await fetch(apiSpezza);
const dataSpezza = await responseSpezza.json();
...

以及渲染Spezza的位置

<>
    ...
    <h1>Roster:</h1>
    <p>Jersey Number: {this.state.roster.jerseyNumber}</p>
    <p>Full Name: {this.state.roster.person.fullName}</p>
    <h1>Spezza:</h1>
    <p>Jersey Number: {this.state.spezza.primaryNumber}</p>
    <p>Age: {this.state.spezza.currentAge}</p>
    <p>Height: {this.state.spezza.height}</p>
    <p>Weight: {this.state.spezza.weight} lbs</p>
    <p>Nationalty: {this.state.spezza.nationality}</p>
    ....
</>

然后创建一个像这样的新组件:

class PlayerComponent extends Component {


    state = {player: {}}

    // Spezza
    const player = `https://statsapi.web.nhl.com/api/v1/people/8469455${this.props.player.person.id}`;
    const playerResponse = await fetch(player);
    const playerData= await playerResponse.json();

    this.setState({layer : playerData})


    render() {
        return (
            <>
      <h1>Roster:</h1>
                <p>Full Name: {this.state.player.fullName}</p>
                <h1>{this.state.player}</h1>
                <p>Jersey Number: {this.state.player.primaryNumber}</p>
                <p>Age: {this.state.player.currentAge}</p>
                <p>Height: {this.state.player.height}</p>
                <p>Weight: {this.state.player.weight} lbs</p>
                <p>Nationalty: {this.state.player.nationality}</p>
            </>
        )
    }
}

并像这样在您的Main组件中使用PlayerComponent:

<>
    ...
    {this.state.roster.length && this.state.roster.map(player => <PlayerComponent player={player}/>)}
    ...
</>

希望这会有所帮助。