Почему снова запускается эффект на дочерний компонент? - PullRequest
0 голосов
/ 06 мая 2020

Мне нужна помощь, чтобы понять, почему приведенный ниже код вызывает inf-рендеринг l oop. На мой взгляд, это должен был быть цикл:

  1. Контейнер рендеринга.

  2. Рендеринг дочернего StrRow.

  3. Запустить эффект в первый раз и вызвать update ().

  4. Изменить состояние контейнера.

  5. Повторно отрисовать контейнер .

  6. Повторно отрендерить chlid StrRow.

  7. НЕ запускать эффект снова, поскольку зависимость не изменилась.

Тем не менее, эффект, похоже, запускается после каждого рендеринга StrRow.

function Container() {
      const [count, setCount] = React.useState(0);

      const update = React.useCallback(() => {
        setCount(count + 1);
      }, [count, setCount]);

      return (
        <div style={{ background: "#ccc", border: "3px solid black" }}>
          Increced Length {count} Times.
          <StrRow update={update} />
        </div>
      );
    }

    function StrRow({ update }) {
      const [str, setStr] = React.useState(">");

      React.useEffect(() => {
        update();
      }, [str, update]);

      return (
        <div style={{ background: "#27b" }}>
          <div>{str}</div>
          <button
            onClick={() => {
              setStr(str + ">");
            }}
          >
            Add Length
          </button>
        </div>
      );
    }

Вот ссылка на песочницу с вызовом update (), закомментированная, чтобы предотвратить инф l oop: https://codesandbox.io/s/compassionate-montalcini-muiod?file= / src / App. js

Обратите внимание, что я не ищу способы исправить или изменить этот код. Я просто хотел бы понять причину проблемы.

Большое спасибо!

Ответы [ 2 ]

2 голосов
/ 06 мая 2020

То, что у вас есть в демоверсии, немного отличается от того, что у вас есть в посте.

Обратите внимание, что то, что вы пишете в сообщении, не вызовет бесконечное l oop, а дочерняя кнопка onClick будет go через следующие шаги

  • Обновить дочернее состояние str
  • Запуск дочернего useEffect и вызов родительского метода обновления
  • функция обновления увеличивает значение счетчика и повторно отображает родительский
  • дочерний компонент повторно визуализируется

Однако в демонстрации у вас есть

   React.useEffect(() => {
    update();
  }, [str, update]);

Однако вышеупомянутый useEffect вызовет бесконечное l oop. Причина в том, что когда функция обновления запускается, она обновляет состояние, что в основном приводит к созданию нового экземпляра обновления при повторной визуализации родительского компонента, поскольку зависимость useCallback изменилась.

Правильный способ определения useCallback будет использовались setCount с функциональным шаблоном и не учитывались как зависимость от useCallback, как показано ниже, и тогда все будет работать нормально

  const update = React.useCallback(() => {
    setCount(prevCount => prevCount + 1);
  }, [setCount]);

Рабочая демонстрация

0 голосов
/ 06 мая 2020

это потому, что update setsState вызывает повторную визуализацию, которая визуализирует ваш <StrRow> компонент, который onMount в useEffect вызывает эту функцию обновления, которая setState..et c, и будет продолжать делать это вечно

...