• 로그인
  • 장바구니에 상품이 없습니다.

home2 게시판 React 게시판 선생님 리액트로 버튼클릭시 메뉴 나타내는거질문있습니다.

선생님 리액트로 버튼클릭시 메뉴 나타내는거질문있습니다.

5 글 보임 - 1 에서 5 까지 (총 5 중에서)
  • 글쓴이
  • #69080

    정중식
    참가자
    Header.jsx
    
    
    import {
      Item,
      List,
      Login,
      Logo,
      Menu,
      MenuItem,
      MenuList,
      StyleHeader,
    } from './styles/Header.styled';
    import { useNavigate } from 'react-router-dom';
    import { FiSearch } from 'react-icons/fi';
    import { useEffect, useRef, useState } from 'react';
    import { Button } from './styles/Button.styled';
    const Header = () => {
      const [isOpen, setIsOpen] = useState(false);
      const menuRef = useRef();
      const navigate = useNavigate();
      const handleIsOpen = () => {
        if (isOpen) {
          setIsOpen(false);
        } else {
          setIsOpen(true);
        }
      };
      useEffect(() => {
        if (menuRef.current) {
          if (isOpen) {
            menuRef.current.classList.remove('close');
            menuRef.current.classList.add('open');
          }
          if (!isOpen) {
            menuRef.current.classList.remove('open');
            menuRef.current.classList.add('close');
          }
        }
      }, [isOpen]);
      return (
        <StyleHeader>
          <Logo onClick={() => navigate('/')}>
            <h1>NewJeans</h1>
          </Logo>
          <List>
            <Item color='#FFBFBF'>
              <span>하니</span>
            </Item>
            <Item color='#f7e600'>
              <span>민지</span>
            </Item>
            <Item color='#F7FCFF'>
              <span>해린</span>
            </Item>
            <Item color='#D0FC5C'>
              <span>다니엘</span>
            </Item>
            <Item color='#9EE0FF'>
              <span>혜인</span>
            </Item>
          </List>
          <Login>
            <div className='user-wrap' onClick={() => handleIsOpen()}>
              Login
            </div>
            <FiSearch className='search-icon' />
          </Login>
          {isOpen && (
            <Menu ref={menuRef}>
              <MenuList>
                <MenuItem>
                  <span className='name'>정중식, welcome! </span>
                </MenuItem>
                <MenuItem>
                  <Button backgroundColor='#00AE68' shadowColor='#007503'>
                    카드작성
                  </Button>
                </MenuItem>
                <MenuItem>
                  <Button backgroundColor='#FFAA40'>마이페이지</Button>
                </MenuItem>
                <MenuItem>
                  <Button backgroundColor='tomato'>로그아웃</Button>
                </MenuItem>
              </MenuList>
            </Menu>
          )}
        </StyleHeader>
      );
    };
    export default Header;
    
    Header.styled.js
    
    
    import styled, { keyframes } from 'styled-components';
    export const menuOpenFrames = keyframes`
     0% {
          height: 0px;
        }
        50% {
          height: 250px;
        }
        100% {
          height: 300px;
        }
    `;
    export const menuCloseFrames = keyframes`
    0% {
          height: 300px;
        }
        50% {
          height: 250px;
        }
        100% {
          height: 0px;
        }
    `;
    export const StyleHeader = styled.header`
      position: relative;
      display: flex;
      align-items: center;
      justify-content: space-between;
      background: #f9f5f2;
      height: 60px;
      padding-left: 10px;
      padding-right: 10px;
    `;
    export const Logo = styled.div`
      height: 100%;
      font-size: 3rem;
      font-weight: bold;
      letter-spacing: -3px;
      cursor: pointer;
    `;
    export const List = styled.ul`
      width: 100%;
      height: 100%;
      display: flex;
      justify-content: center;
      align-items: center;
      padding-right: 50px;
      font-size: 25px;
    `;
    export const Item = styled.li`
      margin-right: 10px;</pre>
    <pre>  span {
        display: flex;
        align-items: center;
        cursor: pointer;</pre>
    <pre>    &:hover {
          font-weight: bold;
          transition-duration: 0.3s;
        }
      }</pre>
    <pre>  & span::before {
        content: '';
        display: block;
        width: 20px;
        height: 20px;
        background: ${(props) => props.color};
        border-radius: 50%;
        margin-right: 5px;
      }
    `;
    export const Login = styled.div`
      display: flex;
      text-align: center;
      font-size: 25px;
      cursor: pointer;</pre>
    <pre>  .user-wrap {
        margin-right: 7px;
        transition: 0.3s;
        &:hover {
          transform: scale(1.2);
        }
      }</pre>
    <pre>  .search-icon {
        transition: 0.3s;
        &:hover {
          transform: scale(1.2);
        }
      }
    `;
    export const Menu = styled.div`
      position: absolute;
      top: 60px;
      left: 0;
      width: 100%;
      z-index: 2;
      background: #f9f5f2;</pre>
    <pre>  &.open {
        animation: ${menuOpenFrames} 0.3s linear forwards;
      }</pre>
    <pre>  &.close {
        animation: ${menuCloseFrames} 0.3s linear forwards;
      }
    `;
    export const MenuList = styled.ul`
      display: flex;
      flex-direction: column;
      padding: 2rem;
      font-size: 25px;
    `;
    export const MenuItem = styled.li`
      display: flex;
      margin-top: 10px;</pre>
    <pre>  &:first-child {
        margin-top: 0;
      }</pre>
    <pre>  & span::before {
        content: '';
        display: block;
        width: 15px;
        height: 15px;
        background: gray;
        border-radius: 50%;
        margin-right: 5px;
      }</pre>
    <pre>  span {
        display: flex;
        align-items: center;
        letter-spacing: -0.3px;
        font-size: 1.56rem;
      }
    `;
    클릭시 잘 나타나기는합니다만, 다시 클릭해서 탭을 닫으면 close애니메이션이 적용이안됩니다..
    혹시 뭐때문에그런거고 어떤식으로 해주면좋을까요?...
    #69107

    정중식
    참가자
    효율적이진않은것같지만 구현했습니다.
    아무래도 isMenu &&(...) 이런식으로 하면 처음 useEffect()에서 if(isMenu)부분은 동작하지만, 요소가 바로 사라져버려서 close 클래스가 안붙는거같아서..
    
    그냥 미리 요소들을 배치시켜놓고 숨겨놓은다음에 클릭시 보이게끔해줬습니다.
    괜찮은가요? ㅠ
      const [isMenu, setIsMenu] = useState('');
     const handleIsOpen = () => {
        if (isMenu) {
          setIsMenu('');
        } else {
          setIsMenu(1);
        }
      };
    
      useEffect(() => {
        if (menuRef.current) {
          if (isMenu) {
            menuRef.current.classList.remove('close');
            menuRef.current.classList.add('open');
          }
          if (!isMenu) {
            menuRef.current.classList.remove('open');
            menuRef.current.classList.add('close');
          }
        }
      }, [isMenu]);
    
    
          <Menu ref={menuRef} visible={isMenu.toString()}>
            <MenuList visible={isMenu.toString()}>
              <MenuItem>
                <span className='name'>정중식, welcome! </span>
              </MenuItem>
              <MenuItem>
                <Button backgroundColor='#00AE68' shadowColor='#007503'>
                  카드작성
                </Button>
              </MenuItem>
              <MenuItem>
                <Button backgroundColor='#FFAA40'>마이페이지</Button>
              </MenuItem>
              <MenuItem>
                <Button backgroundColor='tomato'>로그아웃</Button>
              </MenuItem>
            </MenuList>
          </Menu>
    #69109

    정중식
    참가자
          <Menu className={isMenu ? 'open' : 'close'}>
    좀 매끄럽지않아서 고민중이였는데 ..
    ㅡ. ㅡ 완벽히 구현성공했습니다. 하루온종일 붙잡고있었는데 이렇게쉽게 풀어버릴수가..
    #69112

    정중식
    참가자
    선생님 정말 죄송합니다. 한번만 더 코드 봐주실수 있으실까요?
    문제가, 메뉴를 닫으면 스르륵 닫혀야하는데 아무래도 조건문때문에 닫힐때 애니메이션이 발동되기도전에 요소가 사라져버려서 
    타임아웃을줬습니다. 
    
    
    import {
      Item,
      List,
      Login,
      Logo,
      Menu,
      MenuItem,
      MenuList,
      StyleHeader,
    } from './styles/Header.styled';
    import { useNavigate } from 'react-router-dom';
    import { FiSearch } from 'react-icons/fi';
    import { useState } from 'react';
    import { Button } from './styles/Button.styled';
    const Header = () => {
      const [isMenu, setIsMenu] = useState(false);
      const [isOpen, setIsOpen] = useState(false);
      const navigate = useNavigate();
      const handleMenu = () => {
        setIsMenu(!isMenu);
        if (isOpen) {
          setTimeout(() => {
            setIsOpen(false);
          }, 300);
        } else {
          setIsOpen(true);
        }
      };
      return (
        <StyleHeader>
          <Logo onClick={() => navigate('/')}>
            <h1>NewJeans</h1>
          </Logo>
          <List>
            <Item color='#FFBFBF'>
              <span>하니</span>
            </Item>
            <Item color='#f7e600'>
              <span>민지</span>
            </Item>
            <Item color='#F7FCFF'>
              <span>해린</span>
            </Item>
            <Item color='#D0FC5C'>
              <span>다니엘</span>
            </Item>
            <Item color='#9EE0FF'>
              <span>혜인</span>
            </Item>
          </List>
          <Login>
            <div className='user-wrap' onClick={() => handleMenu()}>
              Login
            </div>
            <FiSearch className='search-icon' />
          </Login>
          {isOpen && (
            <Menu className={isMenu ? 'open' : 'close'}>
              <MenuList className={isMenu ? 'show' : 'hide'}>
                <MenuItem>
                  <span className='name'>정중식, welcome! </span>
                </MenuItem>
                <MenuItem>
                  <Button backgroundColor='#00AE68' shadowColor='#007503'>
                    카드작성
                  </Button>
                </MenuItem>
                <MenuItem>
                  <Button backgroundColor='#FFAA40'>마이페이지</Button>
                </MenuItem>
                <MenuItem>
                  <Button backgroundColor='tomato'>로그아웃</Button>
                </MenuItem>
              </MenuList>
            </Menu>
          )}
        </StyleHeader>
      );
    };
    export default Header;
    
    선생님이 보기에 어떤가요?
    #69114

    codingapple
    키 마스터
    animation보다 transition이 더 쉬울 수 있습니다
5 글 보임 - 1 에서 5 까지 (총 5 중에서)
  • 답변은 로그인 후 가능합니다.

About

현재 월 700명 신규수강중입니다.

  (09:00~20:00) 빠른 상담은 카톡 플러스친구 코딩애플 (링크)
  admin@codingapple.com
  이용약관, 개인정보처리방침
ⓒ Codingapple, 강의 예제, 영상 복제 금지
top

© Codingapple, All rights reserved. 슈퍼로켓 에듀케이션 / 서울특별시 강동구 고덕로 19길 30 / 사업자등록번호 : 212-26-14752 온라인 교육학원업 / 통신판매업신고번호 : 제 2017-서울강동-0002 호 / 개인정보관리자 : 박종흠