useState 사용하기

LSA·2022년 4월 3일
0

이걸해냄

목록 보기
7/8
post-thumbnail

사실 처음 리액트를 접했을때 썼어야 하는건데, 시간이 없어서 쓸 정신도 없었습니다.

팀 프로젝트에서 만든 내비게이션을 예시로 다시 천천히 써봅니다.

useState

공식 문서 설명글(봐도 무슨말을 하는건지 잘 이해는 안감)
리액트의 대표적인 훅이고, 제일 처음 배우는 훅이라고 생각됩니다. 여기서는 함수 기반 상태 관리를 기준으로 작성했습니다.
내비게이션 바에서는 아래와 같은 기능을 구현할 때 사용됐습니다.

1.제품카테고리 버튼을 누르면 하단 서브메뉴가 나옴
2. 하단 카테고리 메뉴 데이터를 불러옴

00. 파일의 구조


Nav라는 폴더 내에 컴포넌트들이 많이 있습니다.

import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Header } from './Header';
import { faBars, faMagnifyingGlass } from '@fortawesome/free-solid-svg-icons';

import { NavDepth2 } from './NavDepth2.js';
import './Nav.scss';

const Nav = () => {
  let [clicked, setClicked] = useState(false);
  function handleCategory(e) {
    !clicked ? setClicked(true) : setClicked(false);
  }

  return (
    <nav className="nav-wrap">
      <div className="content-wrap">
        <Header />
        <div className="nav">
          <ul className="nav-depth1">
            <li className="nav-category" onClick={handleCategory}>
              <FontAwesomeIcon icon={faBars} className="menu-bar" />
              <span>제품카테고리</span>
            </li>
            <li>
              <Link to="/products/new">신상품</Link>
            </li>
            <li>
              <Link to="/products/best">베스트</Link>
            </li>
            <li>
              <Link to="/products/best">,들이기</Link>
            </li>
            <li>
              <Link to="/products/best">위코뷰 스타일링</Link>
            </li>
            <li>
              <Link to="/products/best">기획전</Link>
            </li>
          </ul>
          <div className="search-section">
            <input type="text" className="search-input" />
            <button className="search-btn">
              <FontAwesomeIcon icon={faMagnifyingGlass} />
            </button>
          </div>
        </div>
      </div>
      <NavDepth2 show={clicked} />
    </nav>
  );
};

export default Nav;

깁니다.

01. import

일단 훅을 쓰려면 제일 해야 하는 것은 import로 훅을 끌어와야 한다는 겁니다.

//1. 리액트 훅 사용
import React, { useState, useEffect } from 'react'; 
//2. 리액트 라우터 돔에서 Link 컴포넌트 사용
import { Link } from 'react-router-dom';
//3. fontawesome 아이콘을 사용하기 위해 끌어온 것들
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faBars, faMagnifyingGlass } from '@fortawesome/free-solid-svg-icons';

//커스텀 컴포넌트 header(로고 있는 쪽)
import { Header } from './Header';
//커스텀 컴포넌트 NavDepth2(제품 카테고리 누르면 나오는 부분)
import { NavDepth2 } from './NavDepth2.js';
//css 연결
import './Nav.scss';

02.이벤트 및 함수 선언

제품 카테고리 메뉴를 누르면 NavDepth2 컴포넌트가 생겼다 없어지는 거니까, 제품 카테고리 버튼에 onClick이벤트를 걸어줍니다.

<li className="nav-category" onClick={handleCategory}>
      <FontAwesomeIcon icon={faBars} className="menu-bar" />
      <span>제품카테고리</span>
</li>

그럼 저 handleCategory 함수는 어떤 역할이냐면..

function handleCategory(e) {
    !clicked ? setClicked(true) : setClicked(false);
  }

매개변수로 이벤트를 (통칭 e)받지만 사실 이 함수에서 이벤트는 딱히 하는게 없습니다.지워야겠네요.
저것을 풀어 쓰면 이렇게 됩니다.

if(!clicked){
  	setClicked(true);
}else{
	setClicked(false);
}

clicked의 결과가 거짓이라면,setClicked라는 함수에 true 혹은 false 값을 준다는 아주 단순한 조건...그럼 그 setClickedclicked는 뭐하는애들인데?

03. ustState 사용

let [clicked, setClicked] = useState(false);

생소한 문법이 하나 나왔습니다.useState의 기본 양식입니다.
먼저 배열 하나에는 1개의 변수와 1개의 함수가 들어갑니다.

1.clicked는, 상태를 저장하는 변수 (즉 let clicked;)
2. setClicked는, 상태를 갱신해주는 함수

function setClicked(){
	(무언가의 과정을 거쳐 clicked의 상태가 갱신되는 코드)
   
	return clicked
}
  1. useState훅이 실행됩니다. 소괄호 안에 들어가는 부분은 초기값으로, 즉 clicked의 초기 상태는 false라는 이야기입니다.
let clicked = false;

useState에서는 setClicked라는 함수를 선언만 해주었으므로,
setClicked를 호출해주거나 값을 넣어주는 행위는 아까 썼던 handleCategory 함수에서 진행됩니다.

  1. useState 선언
  • 상태값을 관리할 변수
  • 상태값을 갱신할 함수
  • 상태값을 관리할 변수의 초기값
    들이 선언된다.
  1. 동작시킬 요소에 이벤트 핸들러를 걸어준다.(onClick 같은것들)
  2. 이벤트 핸들러가 걸린 요소에 이벤트가 진행되면, 이벤트 핸들러 내부의 함수가 실행된다.(setClicked(false) 가 되거나 setClicked(true)가 되거나)

4.setClicked의 결과에 따라 clicked의 값이 변경

대충 이런 흐름으로 이해중
끝일까요?아니요...

04. 변수 값을 다른 컴포넌트로 넘기기

지금은 단지 .nav-category 클래스가 달린 요소를 클릭할때마다 clicked의 값은 true거나 false가 될 뿐입니다.

NavDepth2의 컴포넌트가 사라지거나 생겨야 하니까요.

<NavDepth2 show={clicked} />

NavDepth2show라는 임의의 프로퍼티,즉 props를 가지고 있습니다.
show라는 프로퍼티의 값에 clicked의 값을 넣어줄겁니다.

이제 NavDepth2 가 어떻게 생겨먹었는지 뜯어보러 갑니다.

import { useState, useEffect } from 'react';
import { MenuLink, ProductLink } from './Links.js';

const NavDepth2 = show => {
  const [pageCategory, setPageCategory] = useState([]);
  const [sub1Category, setSub1Category] = useState([]);

  useEffect(() => {
    fetch('./data/pageCategoryData.json', { method: 'GET' })
      .then(res => res.json())
      .then(data => {
        setPageCategory(data);
      });
    fetch('./data/sub1CategoryData.json', { method: 'GET' })
      .then(res => res.json())
      .then(data => {
        setSub1Category(data);
      });
  }, []);

  return (
    <div className={`nav-depth2 ${!show.show ? 'nav-disable' : ''}`}>
      <div className="content-wrap">
        <ul className="nav-depth3">
          {pageCategory.map(list => (
            <MenuLink key={list.id} list={list} />
          ))}
        </ul>

        {sub1Category.map(list => (
          <ProductLink key={list.sub1_id} list={list} />
        ))}
      </div>
    </div>
  );
};

export { NavDepth2 };

뭔가 또 많습니다. 지금은 이 부분만 봅니다.

05. className toggle

<div className={`nav-depth2 ${!show.show ? 'nav-disable' : ''}`}>
.
.
</div>

NavDepth2 컴포넌트는 nav-depth2의 클래스 네임을 가진 div 요소로 감싸져 있으며, 이 .nav-depth2 옆에 다중 클래스로 nav-disable을 뗐다 붙였다 할 겁니다.
한마디로 클래스 명을 토글하는 것
저기서 console로 인자로 들어온 show를 출력하면,간단히 이런 모습으로 출력됩니다.

Show:{show:false}
//들어온 인자 show: {Navdepth2의 props show : clicked의 값}

위쪽의 삼항 연산자에서 show.show라고 작성한 것은 이러한 이유 때문입니다.
어쨌든 저 값은 true 아니면 false이기 때문에 조건을 !show.show 라고만 작성해줘도 저기서 true냐 false냐를 확인합니다.

만약 show.show의 값이 false
=> <div className= "nav-depth2 nav-disable" >

만약 show.show의 값이 true
=> <div className= "nav-depth2" >

이런 간단한 동작만으로 카테고리 메뉴의 토글을 구현했습니다.
애니메이션이 없다면 말이지....
여기서 드롭다운 애니메이션이 들어간다면 더 어려워질 것 같습니다.

마무리

비단 이럴 때뿐만 아니라, useState는 상태가 변경되는 컴포넌트를 관리할 때 용이하게 쓰입니다.
다음에는 NavDepth2에 적혀져 있던 것처럼,useState와 useEffect를 사용하여 데이터 관리를 하는 과정을 적겠습니다.

profile
진짜 간단하게 작성한 TIL 블로그

0개의 댓글