在React的`useEffect`钩子中进行多个API获取请求是否总是非常慢?

huangapple go评论54阅读模式
英文:

Is having more than one API fetch request in a React useEffect hook always very slow?

问题

第二段代码比第一段代码更快的原因在于它使用了两个不同的useEffect钩子来处理不同的任务,而不是在一个useEffect中处理所有任务。这有助于提高性能和减少不必要的重复工作。

在第一段代码中,所有工作都在一个useEffect中完成,包括获取行星信息和获取居民信息。这意味着每当currentPlanetNumber更改时,都会触发整个useEffect,即使您只需要更新行星信息或仅获取居民信息。这会导致不必要的重复工作,因为您在每次触发时都重新获取行星信息,即使它没有更改。

而在第二段代码中,行星信息获取和居民信息获取分别在两个不同的useEffect中完成。这意味着只有在currentPlanetNumber更改时才会重新获取行星信息,而只有在currentPlanet更改时才会获取居民信息。这减少了不必要的工作,提高了性能。

通常来说,将相关的操作分成多个useEffect是一个好的做法,因为它可以使代码更具可读性,同时也有助于减少不必要的重复工作。这并不意味着您不能在一个useEffect中处理多个操作,但要注意确保只有在需要时才执行这些操作,以提高性能。

英文:

I am writing a simple application using React to fetch and display data from the Star Wars API. I first fetch information about a particular planet. The response JSON for a given planet contains a bunch of data, including an array of URLs pointing to further data about notable residents of said planet. I next call each of those URLs in order to display a list of the names of the residents of the current planet.

This code works, but is slow as heck:

const url = `https://swapi.dev/api/planets/`;

const [currentPlanetNumber, setCurrentPlanetNumber] = React.useState(1);
const [currentPlanet, setCurrentPlanet] = React.useState({});
const [currentPlanetResidentsDetails, setCurrentPlanetResidentsDetails] =
  React.useState([]);

React.useEffect(() => {
  (async () => {
    const planetData = await fetch(`${url}${currentPlanetNumber}/`).then(
      (response) => response.json()
    );
    setCurrentPlanet(planetData);

    if (planetData.residents.length === 0) {
      setCurrentPlanetResidentsDetails(["No notable residents"]);
    } else {
      const residentsURLs = planetData.residents;
      const residentsNames = await Promise.all(
        residentsURLs.map(async (item) => {
          const name = await fetch(item).then((response) => response.json());
          const newName = name.name;
          return newName;
        })
      );
      setCurrentPlanetResidentsDetails(residentsNames);
    }
  })();
}, [currentPlanetNumber]);

The following code works fairly fast for this:

const url = `https://swapi.dev/api/planets/`;

const [currentPlanetNumber, setCurrentPlanetNumber] = React.useState(1);
const [currentPlanet, setCurrentPlanet] = React.useState({});
const [currentPlanetResidentsDetails, setCurrentPlanetResidentsDetails] =
  React.useState([]);

React.useEffect(() => {
  (async () => {
    const planetData = await fetch(`${url}${currentPlanetNumber}/`).then(
      (response) => response.json()
    );
    setCurrentPlanet(planetData);
  })();
}, [currentPlanetNumber]);

React.useEffect(() => {
  (async () => {
    if (currentPlanet.residents.length === 0) {
      setCurrentPlanetResidentsDetails(["No notable residents"]);
    } else {
      const residentsURLs = currentPlanet.residents;
      const residentsNames = await Promise.all(
        residentsURLs.map(async (item) => {
          const name = await fetch(item).then((response) => response.json());
          const newName = name.name;
          return newName;
        })
      );
      setCurrentPlanetResidentsDetails(residentsNames);
    }
  })();
}, [currentPlanet]);

What makes the second one so much faster? I assumed that they would both take about the same length of time, because the same number of fetch requests get done either way.

Is it a good rule of thumb to not have more than one fetch request an any given useEffect hook?

答案1

得分: 0

不,没有规则指出在给定的useEffect中不能有多个获取请求。

在您的第一个示例中,获取请求是连续触发的,而在第二个示例中它们是并发触发的。

您的第一个示例似乎比第二个更合适。 在第二个示例中,似乎代码执行更快,因为在组件挂载时两个效果都是同时触发的。对于'currentPlanetNumber'的后续更改,两个示例应在相同的时间内执行。

英文:

No, there is no rule of thumb stating not to have more than one fetch request in a given useEffect.

In your first example, the fetch requests are fired consecutively, while in the second example they are fired concurrently.

Your first example seems to be more appropriate than the second. In the second example, it seems to you that the code is executing faster because both effects are firing concurrently when the component mounts. On subsequent changes to 'currentPlanetNumber', both examples should execute in the same amount of time.

huangapple
  • 本文由 发表于 2023年2月8日 21:06:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/75386253.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定