盖茨比:基于window.innerWidth行为不当的条件渲染 [英] Gatsby: React conditional rendering based on window.innerWidth misbehaving

查看:80
本文介绍了盖茨比:基于window.innerWidth行为不当的条件渲染的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

仅在基于Gatsby的网站的生产版本中,基于window.innerWidth的组件的条件渲染似乎无法按预期工作.

Conditional rendering of components based on window.innerWidth seems to not work as intended just in the production build of Gatsby based website.

我用来检查视口宽度的钩子以及用于避免Gatsby节点生产构建错误的全局全局窗口检查如下:

The hook I am using to check the viewport's width, with the additional check for the window global to avoid Gatsby-node production build errors, is the following:

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

然后在我的实际组件中执行以下操作:

Then in my actual component I do the following:

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 构建无法呈现:

It works as it should in development but the production build fails to render:

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

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

When resizing the window below the mediaQueries.lg (1024) it then triggers the actual normal behaviour or conditionally rendering mobile and desktop versions of the component.

再次检查是否是因为渲染仅在resize事件上触发(在development环境中加载时不会触发),我还简单地从钩子console.log()中返回了值并在加载时正确地生产中将其打印出来.

To doublecheck if it was because the render triggers on just the resize event (which it doesn't as it works on load in development environment) I also simply, from within the hook console.log() the return value and it gets printed, in production correctly on load.

产品development版本中也没有任何错误或警告.

There are also no errors or warnings in the production or development build whatsoever.

根据@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阈值下调整大小,它便可以正常工作,然后在桌面设备和移动设备上可以完美地工作,但不会加载.

It now works just when you resize it, once, under the mediaQueries.lg threshold and then it works flawlessly across desktop and mobile but not on load.

推荐答案

我对此有类似的问题,但没有找到解决方案,但可以解决.将以下内容放在渲染的开头:

I had a similar problem to this and haven't found a solution, but a work around. Put the following at the start of your render:

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

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

What I think is happening is that Gatsby is building the page with a style based off the window width (which will be 0 / undefined). Then it's not updating the style in the DOM once the page loads as it thinks it has already performed that action. I think this is a small bug in Gatsby maybe?

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

Either way, the above renders your component blank during the build, forcing it to fully respect all logic when the page loads. Hopefully that provides a solution albeit not a satisfying/complete explanation :)

这篇关于盖茨比:基于window.innerWidth行为不当的条件渲染的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆