[英]React: how to fetch multiple API's
实时代码在这里。
使用 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);
因此,在查看我可以在 NHL API 上找到的文档时,他们似乎没有办法像为团队那样在一个请求中调用多个用户的统计信息。
我的建议是针对请求执行 Promise.all() 或至少将您的等待移动到正在使用数据的位置,以便所有请求可以立即触发,然后等待所有请求返回. 就目前而言,您正在触发第一个请求,等待它回来,然后触发下一个请求。
如果 API 没有接受的路线,比如玩家 ID 数组并返回所有填充的详细信息,那么是的,您需要单独进行所有调用。 有一些方法可以做到这一点,使用 axios 作为建议的评论者之一或Promise.all与本机 Fetch API,但重复如此多的页面可加载时间可能会增加您的通知加载时间。
Promise.all([
fetch(apiSpezza),
fetch(api),
]).then(([data1, data2]) => {
cosnole.log(data1,data2);
})
我建议使用 localhost 调用 API 并且不要直接传递 API URL。
甚至比 Promise.all 更好的是 Promise.allSettled。 与 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());
对不起,答案很长,但我相信这是正确的方法
我会像这样将列表和列表项划分为 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}/>)}
...
</>
希望这可以帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.