【问题标题】:ReactJS hamburger menu is not working after click单击后ReactJS汉堡菜单不起作用
【发布时间】:2021-11-03 10:42:10
【问题描述】:

我的响应式导航栏有问题。当我单击汉堡菜单时,它会将我重定向到一个空白页面,没有其他任何内容。问题是什么?我是新来的反应,我知道我应该采取另一种方法来解决这个问题。

我试图在 Youtube 上找到一些教程,但它们都是使用样式组件制作的。现在我更喜欢坚持使用 css。

这是我的反应组件

import React, {useState} from 'react'
import './navbar.css'
import ProfileIcon from '../../assets/profileIcon.svg'

function Navbar() {

    const [showMenu, setShowMenu] = useState(false)

    const navMenu = document.querySelector('.nav-menu')

    if(showMenu) {
        return navMenu;
    }

    return (
        <nav className="navbar">
            {/* logo */}
            <a href="#" className="nav-logo nav-a">Logo</a>

            {/* navbar buttons */}
            <ul className="nav-menu">
                <li className="nav-item nav-li">
                    <a href="#" className="nav-link nav-a">Components</a>
                </li>
                <li className="nav-item nav-li">
                    <a href="#" className="nav-link nav-a">Articles</a>
                </li>
                <li className="nav-item nav-li">
                    <a href="#" className="nav-link nav-a">About</a>
                </li>
            </ul>

            <img src={ ProfileIcon } className="profile-icon" alt="profile-icon"></img>

            {/* hamburger menu */}
            <div className="hamburger" onClick={() => setShowMenu(!showMenu)}>
                <span className="bar"></span>
                <span className="bar"></span>
                <span className="bar"></span>
            </div>

        </nav>
    )
}

export default Navbar

这是css文件

.navbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 10vh;
    background-color: lightcyan;
    padding-left: 20px;
    padding-right: 20px;
}

.nav-li {
    list-style: none;
    cursor: pointer;
    margin: 5px 10px;
    padding: 5px 10px;
    
}

.nav-a {
    text-decoration: none;
    color: black;
}

.nav-link:hover {
    color: red;
}

.profile-icon {
    width: 20px;
    height: 20px;
    cursor: pointer;
}

.bar {
    display: block;
    width: 25px;
    height: 3px;
    margin: 5px auto;
    -webkit-transition: all 0.3s ease-in-out;
    transition: all 0.3s ease-in-out;
    background-color: #101010;
}

.hamburger {
    display: none;
}

.nav-menu {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 30rem;
}

.nav-logo {
    font-weight: 700;
    font-size: 2.1rem;
}

.nav-link{
    font-size: 1rem;
    font-weight: 400;
    color: black;
}

@media only screen and (max-width: 768px) {
    .nav-menu {
        position: fixed;
        left: -100%;
        top: 4rem;
        flex-direction: column;
        background-color: lightgreen;
        width: 100%;
        text-align: center;
        transition: 0.3s;
        box-shadow: 0 10px 27px rgba(0, 0, 0, 0.05);
        
    }

    .nav-menu.active {
        left: 0;
    }

    .nav-item {
        margin: 2.5rem 0;
    }

    .hamburger {
        display: block;
        cursor: pointer;
    }

    .hamburger.active .bar:nth-child(2) {
        opacity: 0;
    }

    .hamburger.active .bar:nth-child(1) {
        transform: translateY(8px) rotate(45deg);
    }

    .hamburger.active .bar:nth-child(3) {
        transform: translateY(-8px) rotate(-45deg);
    }

    
}

【问题讨论】:

  • React 元素 (&lt;nav&gt;) 不是 DOM 节点。这是一个纯 js 数据结构。您无法从反应组件 const navMenu = document.querySelector('.nav-menu') if(showMenu) { return navMenu; } 返回真实的 DOM 集合
  • 好的,我明白了,你能给我一个关于如何处理这种情况的提示吗?谢谢你的回答

标签: javascript reactjs react-redux react-hooks


【解决方案1】:

React 元素 (&lt;nav&gt;) 不是 DOM 节点。它们是纯 js 数据结构。你不能从 react 组件返回真实的 DOM 集合。

相反,您需要返回正确的 UI 表示状态的值。比如下图。

此外,如果下一个状态取决于前一个状态,您应该使用setState 的回调形式,即setShowMenu(showMenu =&gt; !showMenu)

import React, {useState} from 'react'
import './navbar.css'
import ProfileIcon from '../../assets/profileIcon.svg'

function Navbar() {

    const [showMenu, setShowMenu] = useState(false)

    return (
        <nav className="navbar">
            {/* logo */}
            <a href="#" className="nav-logo nav-a">Logo</a>

            {/* navbar buttons */}
            {showMenu && (
            <ul className="nav-menu">
                <li className="nav-item nav-li">
                    <a href="#" className="nav-link nav-a">Components</a>
                </li>
                <li className="nav-item nav-li">
                    <a href="#" className="nav-link nav-a">Articles</a>
                </li>
                <li className="nav-item nav-li">
                    <a href="#" className="nav-link nav-a">About</a>
                </li>
            </ul>)}

            <img src={ ProfileIcon } className="profile-icon" alt="profile-icon"></img>

            {/* hamburger menu */}
            <div className="hamburger" onClick={() => setShowMenu(showMenu => !showMenu)}>
                <span className="bar"></span>
                <span className="bar"></span>
                <span className="bar"></span>
            </div>

        </nav>
    )
}

export default Navbar

【讨论】:

    【解决方案2】:

    当有人点击汉堡菜单时,你将 showMenu 设置为 true,所以组件重新渲染(因为 showMenu 是一个状态)首先它会看到你的 if 语句;条件为真,所以进去看看return语句,所以返回一个navMenu,但是你没有定义navMenu,navMenu不能是组件(小写字母开头,组件必须大写字母开头)所以它只呈现你的 navMenu 而你的 navMenu 什么都不是!所以你会看到一个空白页。

    您需要有条件地在您的退货中呈现菜单,而不是单独呈现。

    import React, {useState} from 'react'
    import './navbar.css'
    import ProfileIcon from '../../assets/profileIcon.svg'
    
    
    function Navbar() {
    
        const [showMenu, setShowMenu] = useState(false)
    
       
    
       
    
        return (
            <nav className="navbar">
                {/* logo */}
                <a href="#" className="nav-logo nav-a">Logo</a>
    
                {/* navbar buttons */}
               {showMenu && (<ul className="nav-menu">
                    <li className="nav-item nav-li">
                        <a href="#" className="nav-link nav-a">Components</a>
                    </li>
                    <li className="nav-item nav-li">
                        <a href="#" className="nav-link nav-a">Articles</a>
                    </li>
                    <li className="nav-item nav-li">
                        <a href="#" className="nav-link nav-a">About</a>
                    </li>
                </ul>)}
    
                <img src={ ProfileIcon } className="profile-icon" alt="profile-icon"></img>
    
                {/* hamburger menu */}
                <div className="hamburger" onClick={() => setShowMenu(!showMenu)}>
                    <span className="bar"></span>
                    <span className="bar"></span>
                    <span className="bar"></span>
                </div>
            </nav>
        )
    }
    
    export default Navbar
    

    【讨论】:

      【解决方案3】:

      在 React 中,组件渲染的是 propsstate 的函数。

      通常不需要使用document.querySelector 对 DOM 进行任何操作。

      相反,使用showMenu 状态的值有条件地隐藏和显示各种元素...或更改它们的属性。

      在下面的示例中,我将添加和删除“活动”className)。

      function Navbar() {
        const [showMenu, setShowMenu] = useState(false);
      
        return (
          <nav className={`navbar`}>
            {/* navbar buttons */}
            <ul className={`nav-menu ${showMenu && "active"}`}></ul>
      
            {/* hamburger menu */}
            <button className="hamburger" onClick={() => setShowMenu(!showMenu)}>
              hamburger
            </button>
          </nav>
        );
      }
      
      export default Navbar;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-16
        • 2021-11-13
        • 1970-01-01
        • 1970-01-01
        • 2016-12-25
        相关资源
        最近更新 更多