将对API的调用调用中的数据附加到我的状态

我下面有这个函数,它在forEach循环中运行一个函数,如下所示:

async populateSystemData(id) {
    const response = await fetch('https://localhost:44389/api/systemlist/GetSystems/' + id);
    const data = await response.json();
    const result = Object.values(data);
    result.forEach((s) => {
        this.populatePlanetData(s.systemId);
    });
    this.setState({ systems: result,loading: false });
}

这是在循环内执行的功能:

async populatePlanetData(id) {
    const response = await fetch('https://localhost:44389/api/planetlist/GetPlanets/' + id);
    const data = await response.json();
    const result = Object.values(data);
    this.setState({ planets: result,loading: false });
}

这是我将这些数据写出的方式,以便用户可以看到:

{systems.map(s =>
    <tr>
        <td>{s.SystemName}</td>
        <td>
            <table>
                <tr>
                    <td>Planets</td>
                </tr>
                {planets.map(p =>
                    <tr>
                        <td>{p.PlanetName}</td>
                    </tr>
                )}                                      
            </table>
       </td>
    </tr>
 )}

更新populatePlanetData内部状态以使其附加而不是覆盖的最佳方法是什么?

谢谢!

aishenghuo2009 回答:将对API的调用调用中的数据附加到我的状态

async populateSystemData(id) {
    const response = await fetch(`https://localhost:44389/api/systemlist/GetSystems/${id}`);
    const data = await response.json();
    const systems = Object.values(data);

    this.setState({ systems,loading: false });

    // good way to get async list data
    const planetsData = await Promise.all(systems.map(async (system) => {
      const res = await fetch(`https://localhost:44389/api/planetlist/GetPlanets/${system.systemId}`);
      const planetData = await res.json();

      return planetData;
    }));
    const planets = planetsData.map(planet => Object.values(planet));

    this.setState({ planets,loading: false });
}
,

另一种更好地利用React组件的方法

基于作者的评论

there could be 200+ systems,with each system having 1 and up to 50 planets

请考虑拆分成多个组件,而不是遍历函数并具有一个要加载的全局状态。

从概念上讲,我们需要三个组成部分

  • 系统-加载所有系统并显示所有系统
  • 系统-从系统加载所有行星并显示行星
  • 行星-显示行星的内容

让我们继续实施它们

  1. 系统
function Systems({ id }) {
  const [systems,setSystems] = useState([]);

  useEffect(() => {
    const getSystems = async () => {
      const response = await fetch(
        `https://localhost:44389/api/systemlist/GetSystems/${id}`,);
      const data = await response.json();
      setSystems(Object.values(data));
    };
    getSystems();
  },[id]);

  return (
    <table>
      {systems.map((system) => (
        <System system={system} />
      ))}
    </table>
  );
}
  1. 系统
function System({ system: { id,SystemName } }) {
  const [planets,setPlanets] = useState([]);
  const [isLoading,setIsLoading] = useState(true);

  useEffect(() => {
    const getPlanets = async () => {
      const response = await fetch(
        `https://localhost:44389/api/systemlist/GetSystems/${id}`,);
      const data = await response.json();
      setPlanets(Object.values(data));
      setIsLoading(false);
    };
    getPlanets();
  },[id]);

  return (
    <tr>
      {isLoading && <td>Loading...</td>}
      {!isLoading && (
        <>
          <td>{SystemName}</td>
          <td>
            <table>
              <tr>
                <td>Planets</td>
              </tr>
              {planets.map((planet) => (
                <Planet planet={planet} />
              ))}
            </table>
          </td>
        </>
      )}
    </tr>
  );
}
  1. 行星
const Planet = ({ planet: { PlanetName } }) => (
  <tr>
    <td>{PlanetName}</td>
  </tr>
);

您如何看待这种方法?

,

您可以通过传播oldState值来实现

this.setState(({ planets }) => ({ planets: [...planets,...result],loading: false }));

作为一点说明-您不应在populatePlanetData中设置加载。宁可使用地图代替forEach并在其周围放置await Promise.all(result.map(...)),在等待所有异步操作之后,可以将加载状态设置为false。

更新了@zemil的答案讨论中的更改

async populateSystemData(id) {
  const api = `https://localhost:44389/api`;
  const response = await fetch(`${api}/systemlist/GetSystems/${id}`);
  const data = await response.json();
  const systems = Object.values(data);

  this.setState({ systems,loading: false });

  // good way to get async list data
  const planetsData = await Promise.all(
    systems.reduce(async (allSystemsPromise,system) => {
      const allSystems = await allSystemsPromise;
      const res = await fetch(
        `${api}/planetlist/GetPlanets/${system.systemId}`,);
      const planetData = await res.json();

      return [...allSystems,...system];
    },Promise.resolve([])),);
  const planets = planetsData.map((planet) => Object.values(planet));

  this.setState({ planets,loading: false });
}
本文链接:https://www.f2er.com/3165015.html

大家都在问