You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React嵌套数组数据获取:星战主题REST API应用开发问询

嘿,刚好我之前折腾过SWAPI的React小项目,这个嵌套URL的问题其实用Promise.all加React的状态管理就能轻松搞定,我给你一步步拆解:

1. 先搞定基础人物列表的获取

首先用React的useEffect和useState获取people接口的初始数据,先把基础人物信息存起来:

import { useState, useEffect } from 'react';

const StarWarsApp = () => {
  const [people, setPeople] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchPeople = async () => {
      try {
        const res = await fetch('https://swapi.dev/api/people/');
        const data = await res.json();
        // 先存基础人物数据,后面再补关联的嵌套数据
        setPeople(data.results);
        setLoading(false);
      } catch (err) {
        console.error('获取人物数据翻车了:', err);
        setLoading(false);
      }
    };

    fetchPeople();
  }, []);

  if (loading) return <div>加载中... 正在召唤绝地武士 🛐</div>;
2. 写个通用工具函数批量拉取嵌套URL数据

因为像films、species这些字段都是URL数组,咱们写个复用函数来批量请求这些数据,省得重复写代码:

// 传入URL数组,返回对应的数据数组
const fetchNestedData = async (urls) => {
  try {
    // 把每个URL转成fetch请求,然后用Promise.all并行执行
    const requests = urls.map(url => fetch(url).then(res => res.json()));
    return await Promise.all(requests);
  } catch (err) {
    console.error('嵌套数据获取失败:', err);
    return [];
  }
};
3. 拆分出子组件处理单个人物的详情

把单个人物的渲染拆成子组件,这样可以单独处理每个人物的嵌套数据,父组件逻辑会更清爽:

const PersonCard = ({ person }) => {
  const [films, setFilms] = useState([]);
  const [species, setSpecies] = useState([]);
  const [cardLoading, setCardLoading] = useState(true);

  useEffect(() => {
    const fetchPersonDetails = async () => {
      // 并行获取电影和物种数据,提升加载速度
      const [filmsData, speciesData] = await Promise.all([
        fetchNestedData(person.films),
        fetchNestedData(person.species)
      ]);
      setFilms(filmsData);
      setSpecies(speciesData);
      setCardLoading(false);
    };

    fetchPersonDetails();
  }, [person]);

  if (cardLoading) return <div className="card-loading">加载人物详情...</div>;

  return (
    <div className="person-card">
      <h2>{person.name}</h2>
      <p>身高: {person.height}cm</p>
      <p>体重: {person.mass}kg</p>
      <h3>参演电影:</h3>
      <ul>
        {films.map(film => (
          <li key={film.episode_id}>{film.title}</li>
        ))}
      </ul>
      <h3>所属物种:</h3>
      <ul>
        {species.map(specie => (
          <li key={specie.name}>{specie.name}</li>
        ))}
      </ul>
    </div>
  );
};
4. 父组件里映射人物列表

最后回到父组件,把每个人物数据传给子组件渲染就行:

return (
    <div className="app-container">
      <h1>星战人物列表 🚀</h1>
      <div className="people-grid">
        {people.map(person => (
          <PersonCard key={person.url} person={person} />
        ))}
      </div>
    </div>
  );
};

export default StarWarsApp;
额外小贴士
  • 可以加个缓存机制(比如用useMemo或者本地存储),避免重复请求相同的URL(比如很多人物都参演同一部电影,不用每次都拉一遍)
  • 如果数据量很大,记得用上SWAPI的分页参数(?page=2)做分页加载,不然一次性拉太多会慢
  • 错误处理可以再完善点,比如给用户显示友好的错误提示,而不是只在控制台打印

内容的提问来源于stack exchange,提问作者Brandon Benefield

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:14:07