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
请考虑拆分成多个组件,而不是遍历函数并具有一个要加载的全局状态。
从概念上讲,我们需要三个组成部分
- 系统-加载所有系统并显示所有系统
- 系统-从系统加载所有行星并显示行星
- 行星-显示行星的内容
让我们继续实施它们
- 系统
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>
);
}
- 系统
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>
);
}
- 行星
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