如何在 NextJS 中使用 useState 显示或隐藏 div?

发布于 2025-01-17 11:27:28 字数 3396 浏览 0 评论 0 原文

我是新手反应的,但是试图用“桌面标头”和“移动标头”构建一个响应式网站,当用户单击菜单键盘上并在用户单击Close-icon时关闭时,该网站将显示。 我显然做错了,但似乎无法弄清楚问题是什么,我相信Nextjs不知道该打开或关闭什么。

**注意:我正在使用tailwindcss,这是将在索引页面上渲染的组件,

我的代码看起来像这样(简化,没有所有内容):

import React, { useState } from 'react'
import Image from 'next/Image'

function header() {

const \[mobile__Header, setMobile__Header\] = useState(false)

const showMobile__Header = () =\> setMobile__Header(!mobile__Header)

return (\<div\>

        {/* mobile header */}
    
        <div className='absolute flex flex-col w-screen h-screen place-content-between bg-white text-black p-5 z-50'>
    
            <div className='flex items-center justify-between'>
    
                {/* Left Logo */}
    
                <div className='cursor-pointer'>
                    
                </div>
    
                {/* close icon */}
    
                <div className='cursor-pointer' onClick={showMobile__Header}>
                    <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
                    <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
                    </svg>
                </div>
    
            </div>
    
            {/* nav links */}
    
            <div className='flex'>
                <div className='flex flex-col text-xl space-y-3'>
                    
                </div>
            </div>
    
            {/* Social links and languaje changer */}
    
            <div className='flex justify-between font-light'>
                <div>
                    <a className="link" href="">EN</a>
                </div>
    
                <div className='flex flex-col'>
                   
                </div>
    
            </div>
    
        </div>
        
        {/* desktop header */}
    
        <header className="flex w- px-10 py-1 justify-between">
                
    
             <div className="flex">
    
                {/* Left Logos */}
    
                <div className="flex md:hidden cursor-pointer">
                    
                </div>
    
                <div className="hidden md:flex cursor-pointer">
                    
                </div>
    
            </div>
    
            
            <div className="flex items-center">
    
                {/* Menu icon toggle */}
    
                <div className='flex md:hidden cursor-pointer' onClick={showMobile__Header}>
    
                    <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
                    <path strokeLinecap="round" strokeLinejoin="round" d="M4 6h16M4 12h16M4 18h16" />
                    </svg>
    
                </div>
    
                {/* Right Nav Links and language changer */}
    
                <div className="space-x-4 px-5 py-5 hidden md:flex ">
                    
                </div>
    
            </div>
    
            
    
        </header>
    
    
    
        
    </div>
    )}
    export default header

I’m new to React but trying to build a responsive website with a “desktop header” and “mobile header” that is shown when the user clicks on a menu-icon-toggle and closes when the user clicks on Close-icon.
I’m obviously doing it wrong but can’t seem to figure out what the problem is, I believe that NextJS doesn’t know what to open or close.

**Note: I´m using TailwindCSS and this is a component that will be rendered on the index page

My code looks something like this (simplified, without all the content):

import React, { useState } from 'react'
import Image from 'next/Image'

function header() {

const \[mobile__Header, setMobile__Header\] = useState(false)

const showMobile__Header = () =\> setMobile__Header(!mobile__Header)

return (\<div\>

        {/* mobile header */}
    
        <div className='absolute flex flex-col w-screen h-screen place-content-between bg-white text-black p-5 z-50'>
    
            <div className='flex items-center justify-between'>
    
                {/* Left Logo */}
    
                <div className='cursor-pointer'>
                    
                </div>
    
                {/* close icon */}
    
                <div className='cursor-pointer' onClick={showMobile__Header}>
                    <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
                    <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
                    </svg>
                </div>
    
            </div>
    
            {/* nav links */}
    
            <div className='flex'>
                <div className='flex flex-col text-xl space-y-3'>
                    
                </div>
            </div>
    
            {/* Social links and languaje changer */}
    
            <div className='flex justify-between font-light'>
                <div>
                    <a className="link" href="">EN</a>
                </div>
    
                <div className='flex flex-col'>
                   
                </div>
    
            </div>
    
        </div>
        
        {/* desktop header */}
    
        <header className="flex w- px-10 py-1 justify-between">
                
    
             <div className="flex">
    
                {/* Left Logos */}
    
                <div className="flex md:hidden cursor-pointer">
                    
                </div>
    
                <div className="hidden md:flex cursor-pointer">
                    
                </div>
    
            </div>
    
            
            <div className="flex items-center">
    
                {/* Menu icon toggle */}
    
                <div className='flex md:hidden cursor-pointer' onClick={showMobile__Header}>
    
                    <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
                    <path strokeLinecap="round" strokeLinejoin="round" d="M4 6h16M4 12h16M4 18h16" />
                    </svg>
    
                </div>
    
                {/* Right Nav Links and language changer */}
    
                <div className="space-x-4 px-5 py-5 hidden md:flex ">
                    
                </div>
    
            </div>
    
            
    
        </header>
    
    
    
        
    </div>
    )}
    export default header

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吐个泡泡 2025-01-24 11:27:28

您有许多HTML/CSS问题,例如定位和元素结构。

免费的tailwindui示例是一个可供参考的示例。它具有不错的过渡和可访问性,我将其删除为示例。它还使用 headlesseui ,两支球队都建造了。 TW菜单组件在内部处理状态,因此您将无法在其示例中看到逻辑。

以下响应式示例基于上述版本,但没有外部依赖性。

import { useState } from "react";

const Navbar = () => {
  const [isOpen, setOpen] = useState(false);
  const toggleMenu = () => setOpen(!isOpen);

  return (
      <header className="relative bg-white">
        <div className="max-w-7xl mx-auto px-4 sm:px-6">
          <div className="flex justify-between items-center border-b-2 border-gray-100 py-6 md:justify-start md:space-x-10">
            <div className="flex justify-start lg:w-0 lg:flex-1">
              <a href="#">
                <span className="h-8 w-auto sm:h-10">LOGO</span>
              </a>
            </div>
            <div className="-mr-2 -my-2 md:hidden">
              <button
                onClick={toggleMenu}
                className="bg-white rounded-md p-2 inline-flex items-center justify-center text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500"
              >
                Open
              </button>
            </div>
            <nav className="hidden md:flex space-x-10">
              <a href="#" className="text-base font-medium text-gray-500 hover:text-gray-900">
                About
              </a>
            </nav>
          </div>
        </div>
        {isOpen && (
          <div className="absolute top-0 inset-x-0 p-2 transition transform origin-top-right md:hidden">
            <div className="rounded-lg shadow-lg ring-1 ring-black ring-opacity-5 bg-white divide-y-2 divide-gray-50">
              <div className="pt-5 pb-6 px-5">
                <div className="flex items-center justify-between">
                  <div>
                    <span className="h-8 w-auto">LOGO</span>
                  </div>
                  <div className="-mr-2">
                    <button
                      onClick={toggleMenu}
                      className="bg-white rounded-md p-2 inline-flex items-center justify-center text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500"
                    >
                      X
                    </button>
                  </div>
                </div>
                <div className="mt-6">
                  <nav className="grid gap-y-8">
                    <a href="#" className="p-3 flex items-center rounded-md hover:bg-gray-50">
                      About
                    </a>
                  </nav>
                </div>
              </div>
            </div>
          </div>
        )}
      </header>
  );
};

您可能还需要处理路线更改时的菜单关闭。

import { useRouter } from "next/router";
import { useEffect, useState } from "react";

const Navbar = () => {
  const [isOpen, setOpen] = useState(false);
  const toggleMenu = () => setOpen(!isOpen);
  const router = useRouter();

  useEffect(() => {
    const closeMenu = () => isOpen && setOpen(false);
    router.events.on("routeChangeStart", closeMenu);
    return () => {
      router.events.off("routeChangeStart", closeMenu);
    };
  }, [isOpen, router]);

  return (
   ...see above example

You have many HTML/CSS issues like positioning and element structure.

The free tailwindui example is a solid example to reference. It has nice transitions and accessibility baked in, which I removed for the example. It also uses headlessui and heroicons, both were built by the TW team. The TW menu components handle the state internally, so you will not be able to see the logic in their example.

The below responsive example is based on the above-referenced version but without external dependencies.

import { useState } from "react";

const Navbar = () => {
  const [isOpen, setOpen] = useState(false);
  const toggleMenu = () => setOpen(!isOpen);

  return (
      <header className="relative bg-white">
        <div className="max-w-7xl mx-auto px-4 sm:px-6">
          <div className="flex justify-between items-center border-b-2 border-gray-100 py-6 md:justify-start md:space-x-10">
            <div className="flex justify-start lg:w-0 lg:flex-1">
              <a href="#">
                <span className="h-8 w-auto sm:h-10">LOGO</span>
              </a>
            </div>
            <div className="-mr-2 -my-2 md:hidden">
              <button
                onClick={toggleMenu}
                className="bg-white rounded-md p-2 inline-flex items-center justify-center text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500"
              >
                Open
              </button>
            </div>
            <nav className="hidden md:flex space-x-10">
              <a href="#" className="text-base font-medium text-gray-500 hover:text-gray-900">
                About
              </a>
            </nav>
          </div>
        </div>
        {isOpen && (
          <div className="absolute top-0 inset-x-0 p-2 transition transform origin-top-right md:hidden">
            <div className="rounded-lg shadow-lg ring-1 ring-black ring-opacity-5 bg-white divide-y-2 divide-gray-50">
              <div className="pt-5 pb-6 px-5">
                <div className="flex items-center justify-between">
                  <div>
                    <span className="h-8 w-auto">LOGO</span>
                  </div>
                  <div className="-mr-2">
                    <button
                      onClick={toggleMenu}
                      className="bg-white rounded-md p-2 inline-flex items-center justify-center text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500"
                    >
                      X
                    </button>
                  </div>
                </div>
                <div className="mt-6">
                  <nav className="grid gap-y-8">
                    <a href="#" className="p-3 flex items-center rounded-md hover:bg-gray-50">
                      About
                    </a>
                  </nav>
                </div>
              </div>
            </div>
          </div>
        )}
      </header>
  );
};

You will also likely need to handle the closing of the menu on route change.

import { useRouter } from "next/router";
import { useEffect, useState } from "react";

const Navbar = () => {
  const [isOpen, setOpen] = useState(false);
  const toggleMenu = () => setOpen(!isOpen);
  const router = useRouter();

  useEffect(() => {
    const closeMenu = () => isOpen && setOpen(false);
    router.events.on("routeChangeStart", closeMenu);
    return () => {
      router.events.off("routeChangeStart", closeMenu);
    };
  }, [isOpen, router]);

  return (
   ...see above example

听你说爱我 2025-01-24 11:27:28

在不确切知道你要问什么的情况下,这应该会让你走上正确的道路,至少从逻辑的角度来看。

import React, { useState } from 'react'
import Image from 'next/Image'

function header() {

const [mobile__Header, setMobile__Header] = useState(false)

const showMobile__Header = (e) => {
    if (e.target.className.includes('mobile')) {
        setMobile__Header(true)
    } else if (e.target.className.includes('desktop')){
        setMobile__Header(false)
    }
}

return (
    <div>
        <div className='absolute flex flex-col w-screen h-screen place-content-between bg-white text-black p-5 z-50'>
    
            <div className='flex items-center justify-between'>
    
    
                <div className='cursor-pointer'>
                    
                </div>
    
    
                <div className={mobile__Header === true ? 'cursor-pointer-mobile' : 'remove-display'} onClick={showMobile__Header}>
                    <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
                    <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
                    </svg>
                </div>
    
            </div>
    
    
            <div className='flex'>
                <div className='flex flex-col text-xl space-y-3'>
                    
                </div>
            </div>
    
    
            <div className='flex justify-between font-light'>
                <div>
                    <a className="link" href="">EN</a>
                </div>
    
                <div className='flex flex-col'>
                   
                </div>
    
            </div>
    
        </div>
        
        <header className="flex w- px-10 py-1 justify-between">
                
    
             <div className="flex">
    
    
                <div className="flex md:hidden cursor-pointer">
                    
                </div>
    
                <div className="hidden md:flex cursor-pointer">
                    
                </div>
    
            </div>
    
            
            <div className="flex items-center">
    
    
                <div className={mobile__Header === false ? 'cursor-pointer-desktop' : 'remove-display'} onClick={showMobile__Header}>
    
                    <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
                    <path strokeLinecap="round" strokeLinejoin="round" d="M4 6h16M4 12h16M4 18h16" />
                    </svg>
    
                </div>
    
    
                <div className="space-x-4 px-5 py-5 hidden md:flex ">
                    
                </div>
    
            </div>
    
            
    
        </header>
     </div>
    )
}
    export default header

基本上,请确保使用 classNames 区分您的移动按钮和桌面按钮。然后,您根据 className 中的内容设置一个 bolean 指示符。从那里,您可以显示正确的容器,或者使用简单地放置 display: noneCSS 类(在本例中,我使用名称 remove-display 所有这些都是通过内联三元运算符 来完成的,

无论您是切换按钮还是切换整个容器(display: none 时的父 div)。删除里面的所有内容),这种方法适用于 我仍然对你所问的问题感到困惑,但我的解决方案

应该可以让你继续下去。你在两个 div 上都有一个 onClick 函数,并且每个上面的注释都具有误导性。 >关闭图标,另一个说菜单图标切换我不确定我们要切换什么:

这是一个更简洁的方法,它不涉及className。 切换。你这样做是为了实际上可以切换你想要切换的内容:

import React, { useState } from 'react'

function header() {

    const [isActivate, setActive] = useState(false)

    const handleActivate = (e) => {
        !isActivate ? setActivate(true) : setActivate(false)
}

return (
    <div>
        <div>
            <h1 style={{cursor: 'pointer'}} onClick={handleActivate}>
                {isActivate === true ? 'OPEN' : false}
            </h1>
            <h1 style={{cursor: 'pointer'}} onClick={handleActivate}>
                {!isActivate ? 'CLOSE' : false}
            </h1>
        </div>
     </div>
    )
}
    export default header

Without knowing exactly what you are asking, this should set you down the right path, at least from a logic standpoint.

import React, { useState } from 'react'
import Image from 'next/Image'

function header() {

const [mobile__Header, setMobile__Header] = useState(false)

const showMobile__Header = (e) => {
    if (e.target.className.includes('mobile')) {
        setMobile__Header(true)
    } else if (e.target.className.includes('desktop')){
        setMobile__Header(false)
    }
}

return (
    <div>
        <div className='absolute flex flex-col w-screen h-screen place-content-between bg-white text-black p-5 z-50'>
    
            <div className='flex items-center justify-between'>
    
    
                <div className='cursor-pointer'>
                    
                </div>
    
    
                <div className={mobile__Header === true ? 'cursor-pointer-mobile' : 'remove-display'} onClick={showMobile__Header}>
                    <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
                    <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
                    </svg>
                </div>
    
            </div>
    
    
            <div className='flex'>
                <div className='flex flex-col text-xl space-y-3'>
                    
                </div>
            </div>
    
    
            <div className='flex justify-between font-light'>
                <div>
                    <a className="link" href="">EN</a>
                </div>
    
                <div className='flex flex-col'>
                   
                </div>
    
            </div>
    
        </div>
        
        <header className="flex w- px-10 py-1 justify-between">
                
    
             <div className="flex">
    
    
                <div className="flex md:hidden cursor-pointer">
                    
                </div>
    
                <div className="hidden md:flex cursor-pointer">
                    
                </div>
    
            </div>
    
            
            <div className="flex items-center">
    
    
                <div className={mobile__Header === false ? 'cursor-pointer-desktop' : 'remove-display'} onClick={showMobile__Header}>
    
                    <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
                    <path strokeLinecap="round" strokeLinejoin="round" d="M4 6h16M4 12h16M4 18h16" />
                    </svg>
    
                </div>
    
    
                <div className="space-x-4 px-5 py-5 hidden md:flex ">
                    
                </div>
    
            </div>
    
            
    
        </header>
     </div>
    )
}
    export default header

Basically, make sure to differentiate between your mobile button and your desktop button using your classNames. Then, you set a bolean indicator depending on what is in the className. From there, you either display the correct container, or use a CSS class that simply puts display: none (in this case, I used the name remove-display. All that is done with an inline ternary operator.

Whether you are toggling a button, or toggling a whole container (a parent div that when display: none removes all the content inside), this approach works in both scenarios.

I am still confused as to what you are asking but my solution should get you going. You have an onClick function on two divs and the comments above each of those says are misleading. One says close icon and the other says menu icon toggle. I am not sure what we are toggling.

EDIT: Here is a much cleaner way to do it and it involved no className toggling. This will teach you what you are doing so you can actually toggle what you are trying to toggle:

import React, { useState } from 'react'

function header() {

    const [isActivate, setActive] = useState(false)

    const handleActivate = (e) => {
        !isActivate ? setActivate(true) : setActivate(false)
}

return (
    <div>
        <div>
            <h1 style={{cursor: 'pointer'}} onClick={handleActivate}>
                {isActivate === true ? 'OPEN' : false}
            </h1>
            <h1 style={{cursor: 'pointer'}} onClick={handleActivate}>
                {!isActivate ? 'CLOSE' : false}
            </h1>
        </div>
     </div>
    )
}
    export default header
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文