盖茨比:基于window.innerWidth行为不当的条件渲染

时间:2019-10-29 13:37:12

标签: javascript reactjs jsx gatsby server-side-rendering

基于window.innerWidth的组件的条件渲染似乎仅在基于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中正常工作,但是生产构建无法呈现:

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

在mediaQueries.lg(1024)下调整窗口大小时,它会触发实际的正常行为或有条件地呈现该组件的移动版本和桌面版本。

要再次检查是否是因为渲染仅在resize事件上触发(它在development环境中加载时不会触发),我还是从钩子{{ 1}}返回值并在加载后正确地生产中将其打印出来。

产品console.log()版本中也没有任何错误或警告。

根据@Phillip的建议进行编辑

development

现在,只要在mediaQueries.lg阈值下调整大小,它就可以正常工作,然后在桌面和移动设备上可以完美地工作,但不会加载。

3 个答案:

答案 0 :(得分:2)

我猜测现在回答为时已晚,但是在添加事件侦听器之前调用handleResize应该可以。这是我用于相同目的的代码:

  useEffect(() => {
  setWidth(window.innerWidth);
  window.addEventListener("resize", () => {
    setWidth(window.innerWidth);
  });
  return () => {
    window.removeEventListener("resize", () => {});
  };
}, []);

答案 1 :(得分:0)

不要在循环,条件或嵌套函数内调用Hooks from React docs

反应挂钩必须每个渲染上以完全相同的顺序运行。将您的条件移至String回调中:

useEffect

答案 2 :(得分:0)

我有一个与此类似的问题,还没有找到解决方案,但是可以解决。将以下内容放在渲染的开头:

if (typeof window === `undefined`) {
    return(<></>);
}

我认为正在发生的事情是,盖茨比正在建立一种基于窗口宽度(将为0 /未定义)的样式的页面。然后,一旦页面加载就认为它已经执行了该操作,就不会更新DOM中的样式。我认为这可能是盖茨比的一个小虫?

无论哪种方式,以上内容都会在构建过程中使您的组件空白,从而迫使它在页面加载时完全尊重所有逻辑。希望能提供一个解决方案,尽管说明不令人满意:)