React中如何通过双API请求匹配ID实现排名列表展示?
问题描述
我需要调用两个不同的API获取数据:
- API #1:获取未按排名排序的玩家姓名(关联玩家ID)
- API #2:获取按排名排序的玩家ID、排名位置及分数,需要通过匹配ID来获取对应玩家的姓名。
我曾用原生JS异步函数实现过类似逻辑:
<script> getData(); async function getData() { const response = await fetch('http://localhost:3008/api/highscore/players') console.log(response); const data = await response.json(); const req = await fetch('http://localhost:3008/api/players') console.log(req); const info = await req.json(); length = data.players.length; console.log(data); var temp = ""; for (i = 0; i < length; i++) for (j = 0; j < length; j++) { { if (info.players[i].id == data.players[j].id) { temp += "<tr>"; temp += "<td>" + data.players[j].position + "</td>"; temp += "<td>" + info.players[i].name + "</td>"; temp += "<td>" + data.players[j].score + "</td>"; temp += "</tr>"; } } } document.getElementById("data").innerHTML = temp; } </script>
以下是我的React项目代码,需要在此实现该逻辑,请问该如何实现?
import axios from "axios"; import React, { useState, useEffect } from "react"; const Ranking = () => { const [playerName, setPlayerName] = useState([]); const [playerRank, setPlayerRank] = useState([]); const fetchData = () => { const playerAPI = 'http://localhost:3008/api/players'; const playerRankAPI = 'http://localhost:3008/api/highscore/players'; const getINFOPlayer = axios.get(playerAPI) const getPlayerRank = axios.get(playerRankAPI) axios.all([getINFOPlayer, getPlayerRank]).then( axios.spread((...allData) => { const allDataPlayer = allData[0].data.players const getINFOPlayerRank = allData[1].data.players setPlayerName(allDataPlayer) setPlayerRank(getINFOPlayerRank) }) ) } useEffect(() => { fetchData() }, []) return ( <table className="table table-bordered"> <tr> <th>Rank</th> <th>Name</th> <th>Points</th> </tr> <tbody> {playerName?.map((name) => { return ( <tr key={name.name}> <td>{name.name}</td> </tr> ) })} </tbody> </table> ) } export default Ranking
实现思路与代码修改
优化方向
- 将玩家姓名数据转为ID映射对象,替代嵌套循环,把时间复杂度从O(n²)降到O(n),提升性能
- 基于API2返回的已排序排名数据渲染表格,保证排名顺序正确
- 修复React中需用
className替代class的语法问题
修改后的完整代码
import axios from "axios"; import React, { useState, useEffect } from "react"; const Ranking = () => { const [playerMap, setPlayerMap] = useState({}); const [rankedPlayers, setRankedPlayers] = useState([]); const fetchData = () => { const playerAPI = 'http://localhost:3008/api/players'; const playerRankAPI = 'http://localhost:3008/api/highscore/players'; axios.all([axios.get(playerAPI), axios.get(playerRankAPI)]) .then(axios.spread((playerRes, rankRes) => { // 把玩家数组转为{id: 玩家对象}的映射,快速通过ID查找姓名 const nameMap = playerRes.data.players.reduce((map, player) => { map[player.id] = player; return map; }, {}); setPlayerMap(nameMap); // 直接保存已排序的排名数据 setRankedPlayers(rankRes.data.players); })) .catch(err => console.error('数据请求失败:', err)); } useEffect(() => { fetchData(); }, []); return ( <table className="table table-bordered"> <thead> <tr> <th>Rank</th> <th>Name</th> <th>Points</th> </tr> </thead> <tbody> {/* 遍历已排序的排名数据,保证顺序正确 */} {rankedPlayers?.map((rankItem) => { const player = playerMap[rankItem.id]; // 处理ID不匹配的容错情况 if (!player) return null; return ( <tr key={rankItem.id}> <td>{rankItem.position}</td> <td>{player.name}</td> <td>{rankItem.score}</td> </tr> ); })} </tbody> </table> ); } export default Ranking;
关键逻辑说明
- 映射对象优化:通过
reduce将API1的玩家数组转换为以ID为键的对象,后续通过ID直接查找对应玩家,比嵌套循环效率更高 - 按排名顺序渲染:直接遍历API2返回的已排序数据,确保表格展示的排名顺序正确
- 容错处理:增加
if (!player) return null的判断,避免ID不匹配时渲染错误内容
内容的提问来源于stack exchange,提问作者yandry santana
相关产品推荐
相关产品推荐

