【问题标题】:how to conditionally render a mobile nav in gatsby?如何有条件地在 gatsby 中呈现移动导航?
【发布时间】:2021-03-17 17:21:25
【问题描述】:

我是 gatsby 和服务器端渲染的新手,尽管我之前曾使用过很多 react。我编写了一些代码来检查窗口大小,然后根据宽度呈现导航或移动导航。但是,当我尝试测试部署时,我发现使用服务器端渲染时窗口对象不可用。我的问题是,有什么办法可以修改我的代码以使其仍然有效?还是我应该使用 sass 和媒体查询重建所有内容?

import React, { useState, useEffect } from "react"
import { Link, graphql, useStaticQuery } from "gatsby"
// import "./header.module.scss"
import HeaderStyles from "./header.module.scss"
import Logo from "../images/newlogo@2x.png"
import Nav from "./nav"
const Header = () => {
  const data = useStaticQuery(graphql`
    query MyQuery {
      site {
        siteMetadata {
          title
        }
      }
    }
  `)
  const [isDesktop, setDesktop] = useState(window.innerWidth > 768)

  const updateMedia = () => {
    setDesktop(window.innerWidth > 768)
  }

  useEffect(() => {
    window.addEventListener("resize", updateMedia)
    return () => window.removeEventListener("resize", updateMedia)
  })
  const [menuActive, setMenuState] = useState(false)
  return (
    <header
      className={menuActive ? HeaderStyles.mobileNav : HeaderStyles.header}
    >
      <Link to="/" className={HeaderStyles.title}>
        {/* {data.site.siteMetadata.title} */}
        <img src={Logo} height="60" />
      </Link>
      {isDesktop ? (
        <Nav />
      ) : (
        //hamburger
        <div
          onClick={() => setMenuState(!menuActive)}
          className={`${HeaderStyles.navIcon3} ${
            menuActive ? HeaderStyles.open : ""
          }`}
        >
          <span></span>
          <span></span>
          <span></span>
          <span></span>
        </div>
      )}
      {menuActive ? <Nav /> : null}
    </header>
  )
}

export default Header

【问题讨论】:

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


    【解决方案1】:

    您不能在代码中直接使用window object (or other global objects such as document)。这是因为gatsby develop 是由浏览器渲染的,那里有一个window 对象,但是gatsby build 出现在没有window 的Node 服务器(您的机器或您构建的系统)中。

    如果您不想使用 SCSS 和媒体查询(首选版本和更原生的版本)重做您的代码,您需要在每次使用 window 对象之前设置一个条件。在您的情况下,您需要在加载 DOM 树时进行(useEffect 为空 deps[])。像这样的东西应该可以工作:

    import React, { useState, useEffect } from "react"
    import { Link, graphql, useStaticQuery } from "gatsby"
    // import "./header.module.scss"
    import HeaderStyles from "./header.module.scss"
    import Logo from "../images/newlogo@2x.png"
    import Nav from "./nav"
    const Header = () => {
      const data = useStaticQuery(graphql`
        query MyQuery {
          site {
            siteMetadata {
              title
            }
          }
        }
      `)
      const [isDesktop, setDesktop] = useState(false)
    
      useEffect(()=>{
        if(typeof window !== 'undefined'){
          setDesktop(window.innerWidth > 768)
        }
      },[])
    
      const updateMedia = () => {
        setDesktop(window.innerWidth > 768)
      }
    
      useEffect(() => {
        window.addEventListener("resize", updateMedia)
        return () => window.removeEventListener("resize", updateMedia)
      })
      const [menuActive, setMenuState] = useState(false)
      return (
        <header
          className={menuActive ? HeaderStyles.mobileNav : HeaderStyles.header}
        >
          <Link to="/" className={HeaderStyles.title}>
            {/* {data.site.siteMetadata.title} */}
            <img src={Logo} height="60" />
          </Link>
          {isDesktop ? (
            <Nav />
          ) : (
            //hamburger
            <div
              onClick={() => setMenuState(!menuActive)}
              className={`${HeaderStyles.navIcon3} ${
                menuActive ? HeaderStyles.open : ""
              }`}
            >
              <span></span>
              <span></span>
              <span></span>
              <span></span>
            </div>
          )}
          {menuActive ? <Nav /> : null}
        </header>
      )
    }
    
    export default Header
    

    请记住,这种方法会产生一个小的闪烁(几个ms),直到代码知道window 的含义,并且根据您的用例,调整大小时它可能无法正常工作,我们应该重新调整一下代码,让它在那里发挥作用。

    【讨论】:

      猜你喜欢
      • 2022-12-19
      • 2019-01-10
      • 2018-03-09
      • 1970-01-01
      • 2018-03-11
      • 1970-01-01
      • 1970-01-01
      • 2021-12-11
      • 2021-04-17
      相关资源
      最近更新 更多