Реакция useState, useEffect не работает должным образом - PullRequest
0 голосов
/ 31 марта 2019

У меня есть сценарий использования, который я хотел бы решить с помощью перехватчиков React, но он работает не так, как я ожидал.

  • Ожидание: при прокрутке внизу будет отображаться не сверху, а при прокрутке вверху документа оно исчезнет.
  • Текущий: не отображается сверху при прокрутке вниз, но не исчезает при прокрутке вверху документа. Код песочницы ссылка: https://codesandbox.io/s/wkroy1r2xl

Заранее спасибо.

Ответы [ 2 ]

3 голосов
/ 31 марта 2019

Компонент добавляет прослушиватель событий один раз: только при монтировании. В это время он добавляет прослушиватель handleScroll, который «захвачен» с этим конкретным значением isHeaderMoved в данный конкретный момент времени. Всякий раз, когда страница прокручивается, будет вызываться обратный вызов с таким начальным значением isHeaderMoved. Текущий код в основном вызывает handleScroll с false снова и снова.

Короче говоря, вам нужно добавить isHeaderMoved в качестве зависимости от эффекта. Вы также должны переместить слушатель handleScroll внутри эффекта, чтобы его зависимости могли более правильно отслеживаться с помощью плагина hooks eslint.

  useEffect(
    () => {
      const handleScroll = () => {
        if (window.pageYOffset > 0) {
          if (!isHeaderMoved) {
            setIsHeaderMoved(true)
          }
        } else if (isHeaderMoved) {
          setIsHeaderMoved(false)
        }
      }

      window.addEventListener("scroll", handleScroll)
      return () => {
        window.removeEventListener("scroll", handleScroll)
      }
    },
    [isHeaderMoved],
  )

Обратитесь к этим разделам из постов Дана Абромова на эту тему (в которых есть примеры, которые могут объяснить это лучше, чем я):

Стоит пройти весь пост, чтобы полностью понять вещи, если у вас есть время.


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

  useEffect(() => {
    const handleScroll = () => {
      setIsHeaderMoved(window.pageYOffset > 0)
    }

    window.addEventListener("scroll", handleScroll)
    return () => {
      window.removeEventListener("scroll", handleScroll)
    }
  }, [])
0 голосов
/ 31 марта 2019

Это должно сработать, вы должны передать window.pageYOffset или isHeaderMoved на useEffect, чтобы запускать его каждый раз, когда он меняется, если вы оставите его [], он сработает один раз.

  useEffect(
    () => {
      window.addEventListener("scroll", handleScroll);
      return () => {
        window.removeEventListener("scroll", handleScroll);
      };
    },
    [isHeaderMoved]
  );

Я думаю, вы также можете использовать useRef() для этого.

...