【问题标题】:Custom Navbar in GatsbyjsGatsbyjs 中的自定义导航栏
【发布时间】:2021-12-13 03:25:07
【问题描述】:

我遇到了自定义导航栏的问题。我不会撒谎,我确实复制了它,但我想让它变得更好。我遇到的具体问题是在移动端。当我单击导航栏中的链接时,导航栏菜单不会消失。它停留在外面,页面加载到点击的链接。如何使用 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

【问题讨论】:

    标签: javascript css reactjs gatsby styled-components


    【解决方案1】:

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

    与此同时,您可以做的是在您的&lt;li&gt; 中拦截该点击

    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>
          )}
    

    我将帮助您更好地调试(除其他外)。

    【讨论】:

    • 当然。如果可以的话,尝试分享一个代码框,在那里提供帮助比猜测或查看部分代码要快
    • 我可以给你一个我的 github 的链接吗?代码沙箱不工作。不知道是不是因为我有跨环境作为使用 ES6 模块而不是 commonJS 的依赖项
    • 尝试尽可能多地分享信息,但请记住,这不是一个按需平台,克隆项目比在沙箱中实时定制项目要慢。它与常规的&lt;a&gt; 一起工作,因为它刷新了页面(在 React 的范围之外),因此您再次渲染所有内容,因此状态被重置。使用 Gatsby 的路由器,您只需刷新所需的部分(状态不同的部分),这就是为什么我建议使用 CodeSandbox 来检查所有设置的情况。您是否尝试过“肮脏的方法”? (只是为了检查它是否有效)
    • 该解决方案的行为实际上是相同的,感谢您向我展示这种方式,因为我在导航功能上阅读了更多文档。现在我遇到了一个问题,因为 react 说我的导航栏组件正在无限循环中重新渲染。我在一个变量上使用了 useRef(true) 来查看它是否会从循环中逃脱,但不确定为什么现在会导致这种情况。大声笑我创建了一个全新的问题 OP 注释将包含来自导航栏组件的代码
    猜你喜欢
    • 2012-03-12
    • 1970-01-01
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多