Читайте предыдущие реквизиты: слишком много рендеров - PullRequest
3 голосов
/ 05 марта 2020

Я хочу, чтобы кто-то подтвердил мою интуицию по приведенной ниже проблеме.

Моя цель состояла в том, чтобы отслеживать (аналогично здесь ) props.personIdentId и, когда она изменилась, звоните setSuggestions([]).

Вот код:

function Identification(props) {
    let [suggestions, setSuggestions] = useState([]);

    let prevPersonIdentId = useRef(null)
    let counter = useRef(0) // for logs

    // for accessing prev props
    useEffect(() => {
        prevPersonIdentId.current = props.personIdentId;
        console.log("Use effect", props.personIdentId, prevPersonIdentId.current, counter.current++)
    });


    // This props value has changed, act on it.
    if (props.personIdentId != prevPersonIdentId.current) {
        console.log("Props changed", props.personIdentId, prevPersonIdentId.current, counter.current++)

        setSuggestions([])
    }

Но он получал бесконечный l oop, как показано здесь:

enter image description here

Мое объяснение, почему это происходит, заключается в том, что: первоначально, когда он обнаруживает, что реквизит изменился с нуля на 3, он вызывает setSuggestions, который планирует повторный рендеринг, затем следующий повтор -render приходит, но предыдущий запланированный useEffect не успел запуститься, следовательно, prevPersonIdentId.current не обновился, и он снова входит и передает условие if, которое проверяет, изменился ли prop и так далее. Следовательно, бесконечно l oop.

Что подтверждает эта интуиция, так это то, что, используя это условие вместо старого, исправляет код:

 if (props.personIdentId != prevPersonIdentId.current) {
        prevPersonIdentId.current = props.personIdentId;
        setSuggestions([])
 }

Может кто-нибудь подтвердить это или добавить еще разработка

Ответы [ 2 ]

2 голосов
/ 05 марта 2020

useEffect - это асинхронная функция! И вы ставите свое условие в синхронную часть компонента. Синхронная часть вне курса выполняется перед асинхронной.

Переместить условие в useEffect

useEffect(() => {
    if (personIdentId !== prevPersonIdentId.current) {
      prevPersonIdentId.current = personIdentId;
      console.log(
        "Use effect",
        personIdentId,
        prevPersonIdentId.current,
        counter.current++
      );
      setSuggestions([]);
    }
  });

Это может быть прочитано как: При обновлении моего компонента мы проверяем свойство personIdentId на наличие изменений, и если да, мы обновляем ref до это значение и запустить некоторые функции

1 голос
/ 05 марта 2020

Похоже, это то, что происходит:

  1. На первом проходе props.personId равно undefined, а prevPersonIdentId.current равно null. Обратите внимание, что if (props.personIdentId != prevPersonIdentId.current) использует !=, поэтому undefined приводится к null, и вы не вводите if.
  2. Другой рендеринг происходит с такими же условиями.
  3. props.personId теперь изменяется, поэтому вы вводите if.
  4. setSuggestions([]) вызывается, вызывая повторную визуализацию.
  5. l oop forever

Your useEffect никогда не вызывается, потому что вы продолжаете обновлять свое состояние и запускать повторные рендеры до того, как у него появится шанс на его запуск.

Если вы хотите реагировать на изменения в опоре, а не пытаться бросить свои собственные изменения -checking, вы должны просто использовать useEffect со значением, на которое вы хотите ответить в массиве зависимостей:

useEffect(() => {
       setSuggestions([])
 }, [props.personId] );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...