Gatsby: Реагирует на условный рендеринг на основе неправильного поведения window.innerWidth - PullRequest
0 голосов
/ 29 октября 2019

Условный рендеринг компонентов на основе window.innerWidth, похоже, не работает так, как предполагалось, только в production сборке сайта на базе Gatsby.

Крюк, который я использую для проверки ширины области просмотра, с дополнительной проверкой глобального окна, чтобы избежать ошибок производственной сборки узла Gatsby, следующий:

import { useState, useEffect } from 'react'

const useWindowWidth = () => {
  const windowGlobal = typeof window !== 'undefined'

  if(windowGlobal) {
    const [width, setWidth] = useState(window.innerWidth)

    useEffect(() => {
      const handleResize = () => setWidth(window.innerWidth)
      window.addEventListener('resize', handleResize)
      return () => {
        window.removeEventListener('resize', handleResize)
      }
    })

    return width
  }
}

export default useWindowWidth

Тогда в моемФактический компонент Я делаю следующее:

IndexPage.Booking = () => {
  const windowWidth = useWindowWidth()

  return (
    <div className="section__booking__wrapper">
      { windowWidth <= mediaQueries.lg && <IndexPage.Cta /> }
      <div className="section__booking-bg" style={{ backgroundImage: `url(${bg})` }}>
        { windowWidth > mediaQueries.lg && <IndexPage.Cta /> }
      </div>
    </div>
  )
}

Он работает как надо в development, но сборка production не может отрендериться:

<div className="section__booking-bg" style={{ backgroundImage: `url(${bg})` }}>

При изменении размераокно под mediaQueries.lg (1024) затем запускает фактическое нормальное поведение или условно отображает мобильные и настольные версии компонента.

Для двойной проверки, если это произошло, потому что рендеринг срабатывает только на событии resize(что не работает, так как он работает с нагрузкой в ​​development среде). Я также просто изнутри ловушки console.log() возвращает значение, и оно печатается, в продукция правильно при загрузке.

Также нет ошибок или предупреждений в сборке production или development.

Редактировать в соответствии с предложением @Phillip

const useWindowWidth = () => {
  const isBrowser = typeof window !== 'undefined'
  const [width, setWidth] = useState(isBrowser ? window.innerWidth : 0)

  useEffect(() => {
    if (!isBrowser) return false

    const handleResize = () => setWidth(window.innerWidth)
    window.addEventListener('resize', handleResize)

    return () => {
      window.removeEventListener('resize', handleResize)
    }
  })

  return width
}

Теперь он работает только тогда, когда вы измените его размер один раз, под порогом mediaQueries.lg, а затем он работаетбезупречно для настольных компьютеров и мобильных устройств, но не под нагрузкой.

1 Ответ

0 голосов
/ 29 октября 2019

Не вызывать хуки внутри циклов, условий или вложенных функций ( из React docs )

React Hooks должен работать вточно такой же порядок на каждый рендер. Переместите ваше условие в useEffect обратный вызов:

useEffect(() => {
  if (typeof window === 'undefined') return;

  const handleResize = () => setWidth(window.innerWidth);
  window.addEventListener('resize', handleResize);
  return () => {
    window.removeEventListener('resize', handleResize)
  };
});
...