基于window.innerWidth
的组件的有条件渲染似乎仅在基于Gatsby的网站的production构建中无法按预期工作。
我用于检查视口宽度的钩子,以及为避免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阈值下调整大小,它便可以正常工作,然后在台式机和移动设备上可以完美地工作,但不加载。
不要在循环,条件或嵌套函数内调用Hooks(from React docs)
React Hooks必须在every渲染上以完全相同的顺序运行。将您的条件移到useEffect
回调中:
useEffect(() => {
if (typeof window === 'undefined') return;
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize)
};
});