Gatsbyjs 中的自定义导航栏

Custom Navbar in Gatsbyjs

我在使用自定义导航栏时遇到问题。我不想撒谎,我确实复制了它,但我想让它变得更好。我遇到的具体问题是在移动端。当我在导航栏中单击 link 时,导航栏菜单不会消失。它保持在外面,页面加载到被点击的 link。如何使用 useEffect 或 State 或 props 让导航栏滑出视图?

顺便说一下,tailwindCss 和 bootstrap 对我来说是不可能的,因为我想使用样式化组件并提高我的 css 技能。

感谢任何反馈。

编辑代码:

import React, { useState, useEffect, useRef } from "react";
import styled from "styled-components";
import { Link } from "gatsby";

const Navigation = styled.nav`
  display: flex;
  position: sticky;
  position: -webkit-sticky;
  position: -moz-sticky;
  position: -ms-sticky;
  position: -o-sticky;
  background-color: var(--white);
  justify-content: space-between;
  text-transform: uppercase;
  border-bottom: 2px solid var(--light-green-shadow);
  width: 100%;
  margin: 0;
  top: 0;
  padding: 0.5rem 0;
  z-index: 2;
  align-items: center;
  box-sizing: border-box;
  transition: background ease-out 300ms;
  background: ${({ background }) => background ? `var(--light-green-tint)` : `var(--light-green)`};

  @media (max-width: 768px) {
    height: 5vh;
    position: sticky;
    top: 0;
    left: 0;
    right: 0;
    left: 0;
  }
`

const Toggle = styled.div`
  display: none;
  height: 100%;
  cursor: pointer;
  padding: 0 10vw;

  @media (max-width: 768px) {
    display: flex;
  }
`

const Navbox = styled.div`
  display: flex;
  height: 100%;
  justify-content: flex-end;
  align-items: center;
  box-sizing: border-box;
  
  ul {
        display: flex;
        align-items: center;
        width: 100;
        justify-content: end;
        gap: 2rem;
        padding: 0 1rem;
        flex-direction: row;
        li {
            list-style: none;
            transition: transform 500ms;
            :hover {
                transform: translateY(-10px);

            }
            a {
                text-decoration: none;
                transition: color 300ms, transform 500ms;
                color: var(--white);
                :hover {
                    color: var(--light-grey);
                } 
            }
        }
    }

  @media (max-width: 768px) {
    flex-direction: column;
    position: fixed;
    width: 100%;
    justify-content: flex-start;
    padding-top: 10vh;
    background-color: var(--black);
    transition: all 0.3s ease-in;
    top: 6.5vh;
    right: ${({open}) => open ? "0" : "-100%"};
    ul {
        flex-direction: column;
    }
  }
`

const LogoStyle = styled.div`
    margin-left: 2.5rem;
    a {
        text-decoration: none;
        white-space: nowrap; 
        font-size: 1.65rem;
        @media (min-width: 768px) {
            white-space: nowrap;
        }
    }
`;

const Hamburger = styled.div`
  background-color: #111;
  width: 30px;
  height: 3px;
  transition: all .3s linear;
  align-self: center;
  position: relative;
  transform: ${({open}) => open ? "rotate(-45deg)" : "inherit"};

  ::before,
  ::after {
    width: 30px;
    height: 3px;
    background-color: #111;
    content: "";
    position: absolute;
    transition: all 0.3s linear;
  }

  ::before {
    transform: ${({open}) => open ? "rotate(-90deg) translate(-10px, 0px)" : "rotate(0deg)"};
    top: -10px;
  }

  ::after {
    opacity: ${({open}) => open ? "0" : "1"};
    transform: ${({open}) => open ? "rotate(90deg) " : "rotate(0deg)"};
    top: 10px;
  }
`
const Navbar = () => {
  const [navbarOpen, setNavbarOpen] = useState(false);

  const [background, setBackground] = useState(false);
    

  const changeBackground = () => {
      if (window.scrollY > 25) {
          setBackground(true);
      } else {
          setBackground(false);
      }
  }

  const toggleNavbar = () => setNavbarOpen(open => !open);

  useEffect(() => {


      window.addEventListener('scroll', changeBackground);
      console.log(background);
      return () => {
          window.removeEventListener('scroll', changeBackground)
      }
  },[background]);


  return (
    <Navigation background={background}>
       <LogoStyle> 
          <Link to="/">Performant Web Design</Link>
        </LogoStyle>
      <Toggle
        onClick={ toggleNavbar()}
      >
      <Hamburger open={navbarOpen} />
      </Toggle>
      <Navbox open={navbarOpen}>
        <ul>
            <li>
              <Link to='/services'>Services</Link>
            </li>
            <li>
                <Link to="/about">About</Link>
            </li>
            <li>
                <Link to="/contact">Contact</Link>
            </li>
        </ul>
      </Navbox>
    </Navigation>
  )
}

export default Navbar

默认情况下,当导航到另一个页面时,状态应该被重置。 Link 中的 onClick 不会产生任何效果,因为它不是组件接受的 prop(它不是你的组件,它是 Gatsby 的)。尝试在那里调试,因为所有解决方案都会弄脏代码,因为它应该是默认行为。

与此同时,您可以做的是拦截您 <li>

中的点击
const handleClick=(to)=>{
   setNavbarOpen(false);
   navigate(to);
}

<li onClick={handleClick('/services')}>
    <span>Services</span>
</li>

注意:这应该是一个临时解决方案,同时找到未解决状态的原因


按照你所说的让它变得更好,你可以重构它:

  const closeNav = () => {
    if (navbarOpen) {
      setNavbarOpen(false)
    }
  }

  const openNav = () => {
    if (!navbarOpen) {
      setNavbarOpen(true)
    }
  }

进入这个:

  const toggleNavbar = () => setNavbarOpen(!navbarOpen)

还有这个:

{navbarOpen ? <Hamburger open /> : <Hamburger />}

进入这个:

<Hamburger open={navbarOpen} /> 

还有这个:

      {navbarOpen ? (
        <Navbox>
            <ul>
                <li>
                    <Link to="/services" >Services</Link>
                </li> 
                <li>
                    <Link to="/about">About</Link>
                </li>
                <li>
                    <Link to="/contact">Contact</Link>
                </li>
            </ul>
            <IconComponent />
        </Navbox>
      ) : (
        <Navbox open>
            <ul>
                <li>
                    <Link to="/services" onClick={closeNav}>Services</Link>
                </li>
                <li>
                    <Link to="/about">About</Link>
                </li>
                <li>
                    <Link to="/contact">Contact</Link>
                </li>
            </ul>
        </Navbox>
      )}

进入这个:

        <Navbox open={navbarOpen}>
            <ul>
                <li>
                    <Link to="/services" onClick={closeNav}>Services</Link>
                </li>
                <li>
                    <Link to="/about">About</Link>
                </li>
                <li>
                    <Link to="/contact">Contact</Link>
                </li>
            </ul>
        </Navbox>
      )}

我会帮助你更好地调试(除其他外)。