React Gatsby窗口未在服务器端定义



我试图根据窗口的宽度渲染移动导航或常规导航栏。在部署到netlify时,我收到一个错误,即在服务器端渲染期间窗口不可用。我阅读了关于这个问题的gatsby文档,我理解这种情况正在发生,但我无法找到重组这种情况的正确方法,因为我不能在useEffect中使用State,否则我将处理变量的范围。任何帮助都将不胜感激!

这是盖茨比的文档:https://www.gatsbyjs.com/docs/debugging-html-builds/

const Layout = ({ children}) => {
const width = useWindowSize()

let navbar;
if (width > 936) {
navbar = <NavBar />
} else {
navbar = <MobileNav />
}
return (
<OverflowHidden>
{navbar}
<main>{children}</main>
<Footer/>
</OverflowHidden>
)
}
const useWindowSize = () => {
const [size, setSize] = useState(window.innerWidth) 
useEffect(() => {
const handleResize = () => {
setSize(window.innerWidth)
}
window.addEventListener('resize', handleResize)
}, [])
return size
}
const OverflowHidden = styled.div`
overflow-x: hidden;
height: 100%;
`
export default Layout

无论如何,在编译时都无法测量服务器端浏览器视口的大小,所以只需设置一个默认值/回退值即可。此外,您需要确保在组件卸载时清理绑定的事件。

我建议在这里也添加一个debounce例程——并不是所有的浏览器都能为你做到这一点,并且在浏览器调整大小时不断更新布局通常会导致相当差的性能。

总之,你会得到这样的东西:

const useWindowSize = (initialState = "100%", { ttl = 100 } = {}) => {
// initialState is used before the component mounts client-side
const [height, setHeight] = useState(initialState)
useEffect(() => {
const calculateHeight = debounce(() => {
setHeight(window.innerHeight)
}, ttl)
calculateHeight()
window.addEventListener("resize", calculateHeight)
return () => {
// deregister event listener on component dismount
window.removeEventListener("resize", calculateHeight)
}
}, [ttl])
return height
}

最新更新