实时代码为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);
答案 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}/>)}
...
</>
希望这会有所帮助。