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

时间:2020-09-11 19:52:05

标签: reactjs react-hooks gatsby

我正在尝试根据窗口的宽度渲染移动导航或常规导航栏。部署到netlify时,出现错误,即服务器端渲染期间窗口不可用。我阅读了有关该问题的gatsby docs文档,并且了解到这种情况的发生,但是由于无法在useEffect中使用useState,否则我无法弄清楚重组的正确方法,否则我将处理变量的作用域。任何帮助将不胜感激!

这是gatsby文档: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

1 个答案:

答案 0 :(得分:3)

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

我也建议在此处添加一个防反跳例程-并非所有浏览器都会为您执行此操作,并且在调整大小的浏览器中不断更新布局通常会导致性能下降。

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

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
}