2차 프로젝트 - React - Navbar / Sidebar styled component로 구현하기

yojuyoon·2020년 8월 7일
3

프로젝트

목록 보기
7/10

DataUSA 사이트의 Navbar는 Scroll을 감지하여 처음에는 배경색이 없었다가 일정부분 내려가면 배경색이 생기면서 페이지의 타이틀이 추가된다. 스크롤을 감지하는 이벤트를 활용하여 구현할 수 있다.

  const [scrollTop, setScrollTop] = useState(0); //스크롤 위치 상태 초기화
  const [sideMenu, setsideMenu] = useState(null); //추후 구현할 sidebar 상태 초기화(null로 설정한 이유 아래에서 설명)

//useEffect를 사용하여 scrollTop의 상태가 변할 때마다 스크롤 이벤트, 함수 실행
useEffect(() => {
    window.addEventListener("scroll", handleScroll);
  }, [scrollTop]);

//1. scrollTop 메소드를 사용하여 body 또는 선택한 요소의 y축 좌표를 알아내기
//2. scrollTop의 상태를 화면에서의 scroll위치와 내 마우스 커서의 scroll위치를 비교하여 값을 알아냄
//3. scrollTop의 상태를 갱신
  const handleScroll = () => {
    const winScroll = 
      document.body.scrollTop || document.documentElement.scrollTop;
    const { scrollHeight, clientHeight } = document.documentElement;
    const scrollTop = winScroll / (scrollHeight - clientHeight);
    setScrollTop(scrollTop);
  };

1차 프로젝트 때 Nav 바를 멋지게 구현해주신 경배김님 덕분에 수월하게 구현할 수 있었던 것 같다.👍
경배김님.. 감사합니다😊🙏

Nav 상단에 MENU tab을 클릭하면 사이드바가 나온다. 사이드바 자체를 나오게 하는 것은 어렵지 않았으나, 역시나 css 애니메이션에서 한 번 주춤했다. 처음에 부드럽게 나오는 것은 가능했는데 X 버튼을 누르면 너무 갑자기 들어가버리는 바람에 들어가고 나오는 애니메이션을 자연스럽게 구현했던 과정을 살펴보려고 한다.

sidebar는 컴포넌트를 만들어서 조건부 렌더링으로 구현하였다.
Nav 컴포넌트에서 useState로 메뉴탭을 클릭하는 이벤트 함수 안에서 true값으로 변경해준 다음 <SideNav/> 컴포넌트에 props로 sideMenu를 넘겨준다.

//Nav컴포넌트
  const [sideMenu, setsideMenu] = useState(null);

  const showSideMenu = () => {
    setsideMenu(!sideMenu);
    document.body.style.overflow = "hidden";
  };

  const hideSideMenu = (props) => {
    setsideMenu(false);
    document.body.style.overflow = "unset";
  };


  return (
    ...생략
    
 <SideNav sideMenu={sideMenu} hideSideMenu={hideSideMenu} />
)
  
//SideNav 컴포넌트
function SideNav({ sideMenu, hideSideMenu }) {
    return (
    <>
      <SideMenuBackground sideMenu={sideMenu} onClick={hideSideMenu} />
      <SideMenuContainer sideMenu={sideMenu}>
        <MenuContents>
          <div onClick={hideSideMenu} className="closeBtn">
            X
          </div>

...생략
</>

//SideNav styled component
const SideMenuBackground = styled.div`
...생략
  display: ${(props) => (props.sideMenu ? "block" : "none")};
`; // 삼항연산자를 사용해 전달받은 sideMenu의 state에 따라서 렌더링

const SideMenuContainer = styled.div`
...생략
  ${(props) =>
    props.sideMenu !== null &&
    css`
      animation: 0.7s ${(props) => (props.sideMenu ? "showUp" : "showOut")}
        forwards;
    `} 

//애니메이션 자체에 조건부 렌더링을 걸어서 null이 아닐 경우에만 keyframes애니메이션을 실행시키도록 하였다. 
//이유는 boolean값으로만 정의할 경우 초기 값이 false이므로 새로고침 할 때마다 false일 때 보여지는 showOut keyframes가 실행되어서 sideMenu가 갑자기 튀어나왔다가 들어가는 현상이 발생했기 때문이다.
//때문에 초기값은 null로 주어서 아예 sideMenu가 보이지 않도록 하였고 클릭 이벤트가 발생할 때마다 상태를 변경하여 sideMenu를 핸들링하였다.

  @keyframes showUp {
    0% {
      transform: translate(-100%, 0);
    }

    100% {
      transform: translate(0, 0);
    }
  }

  @keyframes showOut {
    0% {
      transform: translate(0, 0);
    }

    100% {
      transform: translate(-100%, 0);
      display: none;
    }
  }
`;

  

역시나 css세계란.. 진입장벽은 낮지만 그 안에 무수히 많은 미로들이 펼쳐져있는 느낌이랄까..?
재밌다가도 힘든 애증의 관계

얼른 다른 컴포넌트와 합쳐서 완성된 페이지를 보고싶다..!

2차 DataWeSA팀 화이팅😊

profile
하고싶은게 많은 사람. Front-end Developer

1개의 댓글

comment-user-thumbnail
2020년 12월 16일

지영님 좋은 글 감사합니다 😇

답글 달기