简体   繁体   中英

How to set the state of a useState hook on page load?

I am trying to create a responsive nav. It has a _ functions:

  1. Display nav links on screen widths > 768px on page load
  2. Not display nav links on screen widths < 768px on page load
  3. Close the nav if left unopened on smaller screen when switched to larger screens (put simply, if a user opens the nav links on mobile, switches to a larger screen size, and then back to mobile, the nav links should be hidden again)

I got 99% of this accomplished, but I think I'm doing it in a hacky way because when I am on smaller screens, the nav links flash for a brief moment, then dissapear. This is obviously not what I am looking for.

Below is a condensed, not styled snippet for easier debugging:

export const Nav = () => {
  const [showNavOnClick, setShowNavOnClick] = useState(false)
  const [hamburgerOpen, setHamburgerOpen] = useState(false)
  const [showNavOnScreenSize, setShowNavOnScreenSize] = useState(true)

  const toggleMenu = () => {
    setShowNavOnClick(!showNavOnClick)
    setHamburgerOpen(!hamburgerOpen)
  }

  useEffect(() => {
    // This line solves all 3 goals, but on page load, the nav links appear, then dissapear in a split moment. 
    if (window.innerWidth < 768) setShowNavOnScreenSize(false)

    const handleResize = () => {
      if (window.innerWidth > 768) {
        setShowNavOnScreenSize(true)
        setShowNavOnClick(false)
      } else if (window.innerWidth < 768) {
        setShowNavOnScreenSize(false)
      }
    }

    window.addEventListener('resize', handleResize)

    return () => {
      window.removeEventListener('resize', handleResize)
    }
  }, [])

  return (
    <nav>
      <a href="/">Home</a>
      <button onClick={toggleMenu}>*</button>
      <a
        href="/about"
        className={`${
          showNavOnScreenSize ||
          showNavOnClick && showNavOnScreenSize != showNavOnClick)
            ? 'visible'
            : 'hidden'
        }`}>
        About
      </a>
    </nav>
  )
}

Below is a video that shows the glitch:

在此处输入图像描述

When I add const [showNavOnScreenSize, setShowNavOnScreenSize] = useState(window.innerWidth >= 768) , I get an error of window is not defined

在此处输入图像描述

You can fix this by changing the default value of the state to be calculated from the width, instead of a hardcoded true :

const [showNavOnScreenSize, setShowNavOnScreenSize] = useState(window.innerWidth >= 768)

If necessary, you can set the default values for your other states in a similar way.

EDIT: Alternatively, try using a layout effect instead so that the rerender is synchronous:

const [showNavOnScreenSize, setShowNavOnScreenSize] = useState(true)

useLayoutEffect(() => {
    if (window.innerWidth < 768) setShowNavOnScreenSize(false)
    // ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM