burger-menu bug with react (flickering)

31 Views Asked by At

I have a strange bug with the burger menu in the Contacts component in my spa. This bug is observed only by me and only in the chrome browser. Other tabs don't have this bug. Who can tell you what the problem is? I am attaching a link to the prototype and a screenshot of the bug. If you need a code, I'm ready to give it to you. enter image description here

https://mizery.space/contacts - prototype link

I found out that if you delete the Address component that is located first, the bug disappears.

My code:

layout

import { useState, useMemo, useEffect } from 'react';
import { useWindowScroll } from '@uidotdev/usehooks';
import { useResize } from '../hooks/useResize';

import Header from './Header/Header';
import Footer from './Footer/Footer';
import Main from './Main/Main';

export default function Layout() {
  const [open, setOpen] = useState(false);
  const [headerFix, setHeaderFix] = useState(false);
  const [headerHeight, setHeaderHeight] = useState(null);
  const [{ y }] = useWindowScroll();

  const handleMenu = () => {
    setOpen(!open);
  };

  const handleOverlayMenu = () => {
    setOpen(false);
  };

  const handleScroll = (offsetY) => {
    if (offsetY >= 150) return setHeaderFix(true);
    if (offsetY === 0) return setHeaderFix(false);
  };

  useMemo(() => handleScroll(y), [y]);

  const sizeWindow = useResize();

  useEffect(() => {
    if (sizeWindow) {
      setHeaderHeight('33px');
    } else {
      setHeaderHeight('150px');
    }
  }, [sizeWindow]);

  return (
    <>
      <Header
        open={open}
        handleMenu={handleMenu}
        headerFix={headerFix}
        sizeWindow={sizeWindow}
      ></Header>
      <Main
        handleOverlayMenu={handleOverlayMenu}
        headerHeight={headerHeight}
      ></Main>
      <Footer handleOverlayMenu={handleOverlayMenu}></Footer>
    </>
  );
}

header

import { Logo } from '../../components/Logo/Logo';
import { Nav } from '../../components/Nav/Nav';
import phone from '../../assets/images/iconPhone.svg';

import styles from './header.module.css';
import classNames from 'classnames';

export default function Header(props) {
  const {
    open = Boolean,
    handleMenu = Function.prototype,
    headerFix = Boolean,
    sizeWindow = Boolean,
  } = props;

  const navRoute = [
    {
      path: '/',
      title: 'Главная',
    },
    {
      path: '/catalog',
      title: 'Каталог',
    },
    {
      path: '/services',
      title: 'Услуги',
    },
    {
      path: '/contacts',
      title: 'Контакты',
    },
  ];


  const headerClasses = classNames({
    [styles['header']]: true,
    [styles['headerActive']]: headerFix,
  });
  const logoClasses = classNames(styles['logo']);
  const navClasses = classNames({
    [styles['nav']]: true,
    [styles['navActive']]: open && sizeWindow,
  });
  const menuClasses = classNames(styles['menu']);
  const burgerClasses = classNames({
    [styles['burger']]: true,
    [styles['burgerActive']]: open,
  });
  const menuLink = ({ isActive }) =>
    classNames({
      [styles['link']]: true,
      [styles['activeLink']]: isActive,
    });

  return (
    <header className={headerClasses}>
      <Logo styleLogo={logoClasses}></Logo>
      <Nav
        navStyle={navClasses}
        linkStyle={menuLink}
        handleMenu={handleMenu}
        navRoute={navRoute}
      ></Nav>
      <div className={menuClasses}>
        <a href="tel:+1234567890">
          <img src={phone} alt="phone" />
        </a>
        <a href="tel:+1234567890">
          <p>+7 (900) 00 00 000</p>
        </a>
        <button className={burgerClasses} onClick={handleMenu}>
          <span></span>
          <span></span>
          <span></span>
        </button>
      </div>
    </header>
  );
}

header styles

@keyframes header-fix {
  0% {
    top: -10%;
    opacity: 0;
  }

  25% {
    opacity: 0.4;
  }

  50% {
    opacity: 0.8;
  }

  100% {
    top: 0;
    opacity: 1;
  }
}

.header {
  position: absolute;
  z-index: 909;
  top: 0;
  right: 0;
  left: 0;
  display: flex;
  width: 100%;
  max-height: 160px;
  align-items: center;
  justify-content: space-between;
  padding: 32px 200px;
  background: var(--color-main);
  box-shadow: 0px 4px 16px 0px rgb(0 0 0 / 48%);
  transition: all 0.5s ease;
}

.logo {
  position: relative;
  z-index: 10;

  & > img {
    width: 120px;
    flex: 0 0 auto;
  }
}

.nav {
  display: flex;
  gap: 60px;
  transition: all 0.5s ease-in-out;
}

.link {
  padding: 10px;
  margin: -10px;
  transition: all 0.5s ease;

  & > p {
    font-size: 20px;
    line-height: 150%;
  }
}

.activeLink {
  color: #fff;
}

.menu {
  display: flex;
  align-items: center;
  gap: 12px;

  & > a {
    flex: 0 0 auto;
    padding: 10px;
    margin: -10px;

    &:nth-of-type(1) {
      position: relative;
      z-index: 10;
    }

    & > img {
      width: 32px;
    }

    & > p {
      font-size: 20px;
      line-height: 150%;
    }
  }
}

.burger {
  position: relative;
  z-index: 9;
  display: none;
}

.headerActive {
  position: fixed;
  animation: header-fix 1s ease;
}

@media (hover: hover) {
  .link:hover {
    color: #fff;
  }
}

@media (hover: none) {
  .link:active {
    color: #fff;
  }
}

@media screen and (max-width: 1540px) {
  .header {
    padding: 32px 50px;
  }

  .nav {
    gap: 30px;
  }
}

/* Portrait tablets and medium desktops */
@media (max-width: 1024px) {
  .header {
    max-height: 42px;
    padding: 10px;
  }

  .logo {
    & > img {
      width: 24px;
    }
  }

  .menu {
    & > a:nth-of-type(1) {
      & > img {
        width: 24px;
      }
    }

    & > a:nth-of-type(2) {
      display: none;
    }
  }

  .nav {
    position: absolute;
    z-index: 9;
    top: -1000px;
    right: 0;
    width: 100%;
    flex-direction: column;
    align-items: center;
    padding: 36px 0;
    background: var(--color-main);
  }

  .link {
    width: 100%;
    text-align: center;

    & > p {
      font-size: 16px;
    }
  }

  .burger {
    display: flex;
    min-height: 22px;
    flex-direction: column;
    justify-content: space-between;
    padding: 10px;
    margin: -10px;
    gap: 4px;

    & > span {
      width: 24px;
      height: 4px;
      flex: 0 0 auto;
      border-radius: 5px;
      background: var(--color-dark);
      transition: all 0.5s ease;
    }
  }

  .burgerActive {
    & > span {
      &:nth-child(1) {
        transform: translate(0, 8px) rotate(45deg);
      }

      &:nth-child(2) {
        opacity: 0;
      }

      &:nth-child(3) {
        transform: translate(0, -8px) rotate(-45deg);
      }
    }
  }

  .navActive {
    top: 0;
  }
}

Address component

    import IconPh from '../../assets/images/tabler_phone.svg';
    import IconEm from '../../assets/images/line-md--email.svg';
    import IconAd from '../../assets/images/tdesign_location.svg';
    
    import styles from './address.module.css';
    
    function Address() {
      const adressInfo = [
        {
          id: 'location',
          img: IconAd,
          text: 'ул. Пушкина, д. 00',
        },
        {
          id: 'phone',
          img: IconPh,
          text: '+7 (900) 00 00 000',
          href: 'tel:+1234567890',
        },
        {
          id: 'email',
          img: IconEm,
          text: '[email protected]',
          href: 'mailto:[email protected]',
        },
      ];
      return (
        <ul className={styles['list']}>
          {adressInfo.map((card) => {
            return (
              <AddressCard
                key={card.id}
                href={card.href}
                img={card.img}
                id={card.id}
                text={card.text}
                cardClass={styles['card']}
              ></AddressCard>
            );
          })}
        </ul>
      );
    }
    
    function AddressCard(props) {
      const { href = '', img = '', id = '', text = '', cardClass = '' } = props;
      return (
        <li className={cardClass}>
          <a href={href}>
            <img src={img} alt={id} />
          </a>
          <a href={href}>{text}</a>
        </li>
      );
    }
    
    export { Address, AddressCard };

Action components

import styles from './action.module.css';
import Container from '../../components/Container/Container';
import { FormSubmit } from '../../components/FormSubmit/FormSubmit';
import { Address } from '../../components/Address/Address';

export default function Action() {
  return (
    <Container containerStyles={styles['background']}>
      <div className={styles['action']}>
        <h2>Контакты</h2>
        <div className={styles['content']}>
          <Address></Address>
          <FormSubmit></FormSubmit>
        </div>
      </div>
      <div className={styles['text']}>
        <p>
          Желаете начать строительство своего дома? Оставьте заявку прямо
          сейчас, и&#160;мы превратим вашу идею в&#160;реальность!
        </p>
      </div>
    </Container>
  );
}
0

There are 0 best solutions below