React如何合并多个API返回数据并通过map遍历渲染
问题核心原因
- 你当前代码中存储状态时,直接取了接口返回的单个字符串字段(
first_name、last_name都是字符串值),状态本身就不是数组类型,自然无法调用map方法遍历 - 取值层级有误:axios封装的响应对象中,实际业务数据在
响应实例.data.data路径下,你当前的取值逻辑没有拿到完整的列表结构 - 日志打印的
allData.data写法有误,allData是按顺序存储所有接口响应对象的数组,本身没有data属性,错误的日志打印会让你误判数据结构 - 多接口数据不需要拆成多个零散的state存储单字段,直接合并为统一的列表结构存储,就能直接遍历渲染
具体实现方案
1. 调整状态定义
去掉冗余的零散单字段state,只需要定义一个存储合并后完整列表的state即可:
const [renderList, setRenderList] = useState([]);
2. 修正接口请求与数据合并逻辑
axios.all拿到所有接口响应后,先分别取出每个接口的有效业务数据,再根据业务需求做合并:
- 如果两个接口返回同结构列表,直接拼接数组合并即可
- 如果两个接口数据需要关联(比如用户数据关联对应航空公司数据),遍历数组按关联字段匹配拼接成完整对象
修正后的请求逻辑代码:
const fetchData = () => { const UserAPI = "https://reqres.in/api/users/2"; const AirlineAPI = "https://reqres.in/api/users/2"; const getUserData = axios.get(UserAPI); const getAirlineData = axios.get(AirlineAPI); axios.all([getUserData, getAirlineData]).then( axios.spread((userRes, airlineRes) => { // 取出两个接口的实际业务数据,注意层级:axios响应.data -> 接口返回体.data才是业务数据 const userData = userRes.data.data; const airlineData = airlineRes.data.data; // --- 合并逻辑,根据业务需求二选一 --- // 场景1:两个列表直接拼接渲染 // const mergedList = Array.isArray(userData) ? [...userData, ...airlineData] : [userData, airlineData] // 场景2:数据关联(示例为按id匹配,可替换成实际关联字段) const mergedList = Array.isArray(userData) ? userData.map(userItem => { const matchAirline = Array.isArray(airlineData) ? airlineData.find(airline => airline.id === userItem.id) : airlineData; return { ...userItem, ...matchAirline } }) : [{...userData, ...airlineData}]; setRenderList(mergedList); }) ); }; // 组件挂载时拉取数据 useEffect(() => { fetchData(); }, []);
3. 页面渲染时遍历数组
修正JSX语法问题(JSX中类名要写className而非原生HTML的class),直接对合并后的数组调用map遍历渲染即可:
return ( <div className="col-md-8"> <div className="artcileData" style={{ marginRight: "85px", height: "80%" }} > <div className="container-fluid border"> <div className="card" style={{ textAlign: "left" }}> <div className="card-body"> <h5 className="card-title">Special title treatment</h5> {/* 遍历渲染列表 */} {renderList.map((item, index) => ( <p className="card-text" key={item.id || index}> <Badge bg="info" style={{ position: "absolute", right: "20px", top: "15px", }} > {item.id} </Badge> 用户名:{item.first_name} <br/> 关联信息:{item.last_name} </p> ))} </div> </div> </div> </div> </div> )
注意点
- 调用
map前最好做类型校验,避免接口返回非数组格式时报错 - 遍历渲染的列表项必须加唯一
key属性,提升渲染性能避免控制台告警 - 后续新增接口时,只需要把请求实例加到
axios.all的参数数组里,在spread回调里按顺序取响应、合并到列表中即可
内容的提问来源于stack exchange,提问作者Still_Learning
相关产品推荐
相关产品推荐

