반응형 헤더

On Netlify => Code

React에서 반응형 헤더를 만드는 것은 복잡할 것이라고 생각했는데 막상 구현해 보니 생각보다 훨씬 간단했습니다.

반응형 헤더를 만들 때 가장 먼저 생각해야 할 것은 크기가 조정될 때마다 화면을 측정하는 방식인 것 같습니다. 그리고 다행스럽게도 자바스크립트는 정확히 그 목적을 위한 eventListener, resize eventListener를 제공합니다.

반응형 헤더를 만드는 목표를 달성하기 위해 해당 eventListener를 어떻게 활용할 수 있는지 봅시다.

// CustomHooks.js
import { useEffect, useState } from 'react';

export const useWindowWidthAndHeight = ()=>{
    // 1- Get the size of window 
    let windowInnerSize = [window.innerWidth, window.innerHeight];

    // 2- Define the state variable windowSize and pass windowInnerSize as its initial value
    let [ windowSize, setWidowSize ] = useState(windowInnerSize);

    useEffect(()=>{
        const changeWindowSize = ()=>{
            setWidowSize([window.innerWidth, window.innerHeight]);
        }
        /* 3- add a 'resize' eventListener to window so that whenever 
the size of window changes the state variable windowSize changes and the component re-renders */
        window.addEventListener("resize", changeWindowSize);

        // 4- cleanup the 'resize' eventListener
        return ()=> window.removeEventListener('resize', changeWindowSize);
    }, []);
    // 5- return the window size
    return windowSize;
}


여기에서 useWindowWidthAndHeight 라는 사용자 지정 후크를 만듭니다.

내부useWindowWidthAndHeight:
먼저 windowInnerSize 의 현재 너비와 높이를 저장할 window 변수를 만듭니다.
둘째, windowInnerSize Hook을 사용하여 생성한 상태 변수windowSize의 초기 값으로 useState를 사용합니다.
셋째, useEffect Hook을 선언하여 resize eventListner를 추가하여 창resize이 발생하면 changeWindowSize()가 화면의 새로운 측정windowSize 및 width로 변경height하도록 합니다.
마지막으로 window 의 가장 최근에 측정된 너비와 높이를 반환합니다.

이제 헤더를 생성해 보겠습니다.

// Header.js
import React from 'react';
import Navbar from './Navbar';
import { Link } from 'react-scroll'; // react-scroll is a library for scrolling in React
import SmallScreensNavbar from './SmallScreensNavbar';
import { useWindowWidthAndHeight } from './CustomHooks';

const Header = () =>{
    // use our custom hook to get the the window size
    const [width, height] = useWindowWidthAndHeight();
    return(
        <header>
            <div className="header-inner">
                <Link to="Home" 
                      smooth={true} 
                      className="logo nav-link">
                      RH
                </Link>
                {/*if the width of the window is bigger than 1000px use <Navebar/>,
                   else user <SmallScreensNavbar/>*/}
                { width > 1000 ?
                <Navbar navClass="nav-big"
                        linkClassName="nav-big-link"/>
                :
                <SmallScreensNavbar navClass="nav-small"
                                    linkClassName = "nav-small-link"
                />
                } 
            </div>
        </header>
    )
}

export default Header;


이제 너비가 1000px보다 큰 화면과 작은 화면을 위한 두 개의 탐색 모음 구성 요소를 만들어야 합니다.

//Navbar.js
import React from 'react';
import { Link } from 'react-scroll';

const Navbar = ({navClass, linkClassName}) =>(
    <NavComponent navClass={navClass}
                  linkClassName = {linkClassName}
    />
);

export const NavComponent = ({onClick, navClass, linkClassName})=>(
  <nav className={navClass}>
      {["Projects", "About", "Contact", "Footer"].map(section=>
        <Link to={section}
              smooth={true}
              className={linkClassName}
              onClick={onClick}>
            {section}
        </Link>
      )}
  </nav>
)
export default Navbar;


작은 화면의 경우:

//SmallScreensNavbar.js
import React, { useState } from 'react';
import { NavComponent } from './Navbar';

const SmallScreensNavbar = () =>{
    // declare 'translate' as a state variable
    let [translate, setTranslate ] = useState(true);
    return(
        <div> 
             <button className="hamburger-btn"
                     onClick= {()=> setTranslate(!translate)}>  {/* toggle translate */}
                  {/* change the btn text based on whether translate is true or false */} 
                 {translate?<span>&#9776;</span>:<span>&times;</span>}
             </button>
             {/*hide and show the sidebar list based on whether translate is true or false*/}
             <div id="sidebar-list" className={`${translate? "addTransiton": "removeTransition"}`}>
                <NavComponent
                    navClass="nav-small"
                    linkClassName = "nav-small-link"
                    onClick = {()=>setTranslate(true)}  //set translate to true to hide the sidebar list
                />
             </div>
        </div>
    )
}
export default SmallScreensNavbar;


이제 이것이 작동하려면 CSS를 추가해야 합니다.

header{
    position: fixed;
    top: 0;
    height: 70px;
    background-color: rgb(197, 178, 178);
    width: 100%;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    box-shadow: 1px 1px 1px 1px rgba(116, 110, 110, 0.199);
}
.header-inner{
    width: 90%;
    display: flex;
    align-items: center;
    justify-content: space-between;
}
.hamburger-btn{
    font-size: 1.3rem;
    position: absolute;
    bottom: 0;
    width: 40px;
    height: 35px;
    right: 30px;
    outline: none;
    background-color: rgb(134, 125, 125);
    color: whitesmoke;
}
.addTransiton{
    transform: translateX(170px);
    transition: transform 0.5s ease-in-out;
}
.removeTransition{
    transform: translateX(20px);
    transition: transform 0.5s ease-in-out;
}

#sidebar-list{
    background-color: rgb(134, 125, 125);
    height: 90vh;
    width: 170px;
    position: absolute;
    z-index: 2000;
    right: 0;
    top: 0;
    margin-top: 70px;
}
.nav-big{
    list-style: none;
    display: flex;
    justify-content: space-around;
    width: 70%;
    font-weight: bold;
}

.nav-big-link{
   cursor: pointer;
   color: white;
   text-decoration: none !important;
}

.nav-small{
    display: flex;
    flex-direction: column;
    text-align: center;
    justify-content: space-around;
    margin: auto;
    height: 40%;
    margin-top: 50px;
    width: 80%;
}
.nav-small-link{
    cursor: pointer;
    color: whitesmoke;
    padding-bottom: 5px;
}



이제 모든 것이 작동해야 합니다.
읽어주셔서 감사합니다. :)

참조:
Stackoverflow 화면의 너비와 높이를 측정하는 방법을 알아보세요.

좋은 웹페이지 즐겨찾기