React.js sidebar (useRef, useEffect 필요 X)

강정우·2023년 1월 17일
1

react.js

목록 보기
30/45
post-thumbnail
post-custom-banner

Sidebar 구현하기

  • 최근 React로 프로젝트를 진행하며 Side를 구현할 일이 생겼다.
    하지만 모두 Ref와 Effect 훅을 사용하여 구현하는데 문제는
    모든 요소가 한 컴포넌트에 몰려있어 lean하지 못한 컴포넌트가 탄생한다.

목표

  1. 네비게이션과 사이드 바 메뉴 컴포넌트는 따로 구성하기
  2. 직관적인 코드로 작성하기

구동방식

  1. 우선 변경사항이 있으니 state를 선언, 네비 컴포넌트(부모요소)에서 클릭을 하면 setState를 true로 바꾸어준다.
  2. 사이드바 컴포넌트(자식 요소)에서 X를 클릭하면 다시 state를 false로 만들어준다.
  3. 요 state를 기반으로 classname을 동적으로 부여한다. 끝

  • 가장 최상단에서 고정되어있을 네비게이션 메뉴 bar로 어떤 페이지에서든 메뉴버튼을 클릭하여 바로 다양한 페이지에 접근이 가능하도록 설계하였다.
import classes from "./Navigation.module.css";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faBars} from "@fortawesome/free-solid-svg-icons";
import {useState} from "react";
import Sidebar from "./Sidebar";

const Navigation = props => {
  // 변경사항을 감지하기위한 state를 선언
    const [menuOn, setMenuOn] = useState(false);
  // X를 click 하면 false
    const menuOffTrigger = () => {
        setMenuOn(false);
    }
  //  메뉴 아이콘을 클릭하면 true
    const menuOnTrigger = () => {
        setMenuOn(true);
    }
  // 실질적인 animation을 담고 있는 css 들
    const menuOnClass = classes.menuOn;
    const menuOffClass = classes.menuOff;
  // jsx코드
    return (
        <div className={classes.navigation}>
            <div className={classes.wrapper}>
                <div className={`${menuOn ? menuOnClass : menuOffClass}`}>
                    <Sidebar onMenuOff={menuOffTrigger}/>			<== 요게 사용자정의 컴포넌트
                </div>
                <div className={classes.menuIcon}>
                    <FontAwesomeIcon icon={faBars} className={classes.menu}
                                     onClick={menuOnTrigger}/></div>
                <div>
                    <span>사용자이름</span>
                    <span>사진</span>
                    <span>로그인</span>
                </div>
            </div>
        </div>
    )
}
export default Navigation;
import classes from "./Sidebar.module.css";
import comLogo from "../../assets/img/comLogo.png"
import userImg from "../../assets/img/img3.png"
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faX} from "@fortawesome/free-solid-svg-icons";
import {useRef} from "react";

const Sidebar = props => {

    return (
        <section className={classes.sidebar}>
            <div className={classes.left}><FontAwesomeIcon onClick={props.onMenuOff} icon={faX}/></div> <== 요기에 onClick
            <div className={classes.comLogo}>
														
              										...
            
        </section>
    )
}
export default Sidebar;

Css

  • 별로 궁금해 하진 않겠지만 혹시 몰라 css를 남겨본다
.navigation {
    display: flex;
    width: 100%;
    border: black 1px solid;
    justify-content: center;
    position: fixed;
    z-index: 99;
    background-color: white;
}
.wrapper {
    width: 80%;
    height: 3rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    background-color: white;
    position: relative;
}
.menuIcon{
    display: flex;
    position: absolute;
    left: 0;
}
.menu {
    cursor: pointer;
}
.menuOn {
    transition: 1s;
    transform: translateX(210px);
}
.menuOff {
    transition: 1s;
    transform: translateX(-210px);
}
.left {
    display: flex;
    justify-content: right;
    cursor: pointer;
}
.sidebar {
    position: absolute;
    left: -370px;
    top: 0px;
    width: 200px;
    height: 95vh;
    padding: 2%;
    background-color: white;
    border-radius: 5vh;
    border: black solid 0.5px;
}
.wrapper {
    z-index: 99;
}
.comLogo {
    display: flex;
    justify-content: center;
    margin-bottom: 1rem;
}
.circle {
    height: 6rem;
    width: 6rem;
    margin: 0 auto;
    border: black solid 1px;
    border-radius: 3rem;
    cursor: pointer;
}
.comDesc {
    font-weight: bolder;
    font-size: large;
    margin-bottom: 1rem;
}
.menuBar {
    display: flex;
    width: 100%;
    height: 3rem;
    border: black solid;
    border-width: 1px 0;
    margin: 1%;
    align-items: center;
    cursor: pointer;
}
.logContainer{
    position: absolute;
    bottom: 50px;
    left: 0px;
    padding: 1rem;
}
.userContainer {
    display: flex;
    justify-content: center;
}

.userImg{
    width: 3rem;
    height: 3rem;
    border-radius: 1.5rem;
    overflow: hidden;
    border: solid black 1px;
    margin: 1rem auto;
    cursor: pointer;
}
.userInfo {
    width: 5rem;
    padding: 0 1rem;
    cursor: pointer;
}
.footer {
    margin-top: 1rem;
    font-size: smaller;
    color: gray;
}
profile
智(지)! 德(덕)! 體(체)!
post-custom-banner

0개의 댓글