Почему это создает бесконечный цикл рендеринга с перехватчиками React? - PullRequest
0 голосов
/ 02 июля 2019

Я пытаюсь визуализировать названия пива как элементы H1 в алфавитном порядке, и я новичок в React Hooks, но это, кажется, вызывает цикл повторного рендеринга

Компоненту Beer передается массивпиво в качестве реквизита из компонента Home, который использует хук useEffect, который, как я подозреваю, может быть виновником, хотя я не уверен.

const Beer = ({ beer }) => {
  const [beers, setBeers] = useState([]);
  let rendered;
  if (beer === undefined) {
    rendered = <Spinner />;
  } else {
    rendered = beer.map(beer => beer.name);
    setBeers(rendered.sort());
    rendered = beers.map(beer => <h1>{beer}</h1>);
  }

  return <div>{rendered}</div>;
};

const Home = () => {
  const [beers, setBeers] = useState();
  useEffect(() => {
    const getBeers = async () => {
      const beerData = await fetch('https://api.punkapi.com/v2/beers');
      const beers = await beerData.json();
      console.log(beers);
      setBeers(beers);
    };
    getBeers();
  }, []);

  return (
    <div>
      <h1>Punk Beers</h1>
      <Beer beer={beers} />
    </div>
  );
};

Я ожидаю, что будет представлен список элементов H1, но это приведет кбесконечный цикл рендеров.

1 Ответ

1 голос
/ 02 июля 2019

Когда вы вызываете setBeers внутри Beer React выполнит повторную визуализацию компонента (т.е. повторно выполнит функцию) с предоставлением обновленного значения для переменной состояния beers.

Youкак правило, не нужно копировать реквизит в такое состояние.Если у вас есть компонент, который выполняет дорогостоящую операцию с реквизитом перед отображением, вы можете использовать памятку для кэширования результата .

В этом случае простая сортировка beers недорого, если ваш массив не состоит из тысяч и тысяч элементов, поэтому оптимизация не требуется.

const Beer = ({ beers }) => (
  beers ? (
    [...beers].sort().map((beer, index) => 
      <h1 key={index}>{beer}</h1>
    )
  ) : (
    <Spinner />
  )
)

const Home = () => {
  const [beers, setBeers] = useState();
  useEffect(() => {
    const getBeers = async () => {
      const beerData = await fetch('https://api.punkapi.com/v2/beers');
      const beers = await beerData.json();
      console.log(beers);
      setBeers(beers);
    };
    getBeers();
  }, []);

  return (
    <div>
      <h1>Punk Beers</h1>
      <Beer beers={beers} />
    </div>
  );
};
...