2023-09-07 15:27:21

 

 

React Hooks

React Hooks는 React 16.8 버전에서 도입된 기능으로 함수형 컴포넌트에서도 상태 관리와 생명 주기 기능을 사용할 수 있게 해줍니다. Hook을 이용하여 기존 Class 바탕의 코드를 작성할 필요 없이 상태 값과 여러 React의 기능을 사용할 수 있으므로 함수형 컴포넌트를 사용하는데 있어 더욱 편리하고 유연하게 개발 할 수 있습니다.

React에서 제공하는 내장 hook과 별도의 custom hooks이 만들어져 있기 때문에 로직을 재사용하고 코드를 더욱 간결하게 만들 수 있습니다. 

 

State Hook(useState)

useState는 현재의 state 값과 그 값을 업데이트 하는 함수를 쌍으로 제공하여 이벤트 핸들러나 다른 곳에서 호출할 수 있습니다. 

초기 상태를 인자로 받아 현재 상태와 그 상태를 업데이트하는 함수를 튜플로 반환합니다.

import React, { useState } from 'react';

function Example() {
  // "count"라는 새 상태 변수를 선언
  // useState의 매개변수가 count의 초기값
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      {/* 버튼을 누르면 count의 값이 1씩 증가 */}
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

 

Effect Hook(useEffect)

side effects를 함수형 컴포넌트에서 다루기 위한 Hook으로 데이터를 가져오거나 DOM 조작, 이벤트 리스너 등록 및 제거와 같은 작업에 사용됩니다.

useEffect(()=>{});

useEffect(()=>{},[]);

useEffect(()=>{},[count]);

useEffect(()=>{},[count,count2]);

각각의 차이점을 알고가는게 좋습니다. 

import React, { useState, useEffect } from 'react';

function ExampleComponent() {
  const [count, setCount] = useState(0);
  const [count2, setCount2] = useState(0);

  // useEffect(()=>{});
  useEffect(()=>{
  	console.log("컴포넌트가 렌더링 될 때마다 로그 출력");
  });
  
  // useEffect(()=>{},[]);
  useEffect(()=>{
	console.log("컴포넌트가 마운트될때 한 번만 실행");
  },[]);
  
  // useEffect(()=>{},[count]);
  // 배열에 상태값이 있으면 그 상태값이 변하는지 주시
  useEffect(()=>{
  	console.log("count의 상태가 변하면 출력");
  },[count]);

  // useEffect(()=>{},[count, count2]);
  useEffect(() => {
  	console.log("count, count2 둘 중 하나라도 상태값이 변하면 로그 출력");
  }, [count, count2]);

  return (
    <div>
      <p>Count: {count} | Count2: {count2}</p>
      <button onClick={() => setCount(count + 1)}> + Count </button>
      <button onClick={() => setCount2(count2 + 1)}> + Count2 </button>
    </div>
  );
}

 

달력 만들기

useState와 useEffect를 사용하여 달력을 만들어 보며 hook과 component에 대한 연습 진행

프로젝트 구조 

 

초기 설정

React 프로젝트 파일 생성

npx create-react-app calender

 

components/Container.jsx

현재 월을 기준으로 일수를 계산

// rafce를 입력하여 자동완성으로 기본 구조 생성
import React from "react";

function DateArr(Year, Month) {
  let getArr = [];
  let nullArrBefore = [];
  let nullArrAfter = [];
  let getDay = 0;

  // 월의 자리수를 맞추기 위해 1자리 월의 경우 0을 붙여줌
  if (Month < 10) {
    getDay = new Date(`${Year}-0${Month}-01`).getDay();
  } else {
    getDay = new Date(`${Year}-${Month}-01`).getDay();
  }

  // 이번달 일수를 가져옴
  const getArrlength = new Date(Year, Month, 0).getDate();

  // 숫자에 일을 붙여 배열에 저장
  for (let i = 1; i < getArrlength + 1; i++) {
    getArr.push(i + " 일");
  }

  // 앞 부분에 빈공간을 null로 채우기 위해 오늘 요일만큼 null을 채움
  for (let j = 0; j < getDay; j++) {
    nullArrBefore.push(null);
  }

  const Arrlength = 42 - (getArr.length + nullArrBefore.length);

  // 42칸의 배열중 요일수 + null로 채운만큼의 길이를 빼고난 나머지 만큼 null로 채움
  for (let x = 0; x < Arrlength; x++) {
    nullArrAfter.push(null);
  }

  // 앞을 null로 채운뒤 요일을 넣고 남은 공간을 null로 채움
  let Arr = [...nullArrBefore, ...getArr, ...nullArrAfter];

  return Arr.map((e) => (
    <div className="dates">
      <span>{e}</span>
    </div>
  ));
}

const Container = ({ Year, Month }) => {
  return <div className="ContainerWrap">{DateArr(Year, Month)}</div>;
};

export default Container;

 

components/Footer.jsx

달력의 맨 아래 공간에 글 출력(없어도 됨)

import React from "react";

// <> 이거로 쓰닌까 div가 따로 만들어지는게 아니라 제일 하단에 span 한줄만 붙음
const Footer = () => {
  return (
    <>
      <span className="FooterSpan">완성!</span>
    </>
  );
};

export default Footer;

 

components/Header.jsx

달력의 윗부분에 대한 내용 출력

import React, { useEffect, useState } from "react";
import Container from "../components/Container";

const Header = () => {
  let getYear = new Date().getFullYear();
  let getMonth = new Date().getMonth() + 1;

  const [active, setActive] = useState(false);

  // active 속성이 바뀌는걸 감지
  useEffect(() => {}, [active]);

  function ContainerOnOff() {
    const ContainerWrap = document.querySelector(".ContainerWrap");
    if (!active) {
      ContainerWrap.classList.add("active");
      setActive(true);
    } else {
      ContainerWrap.classList.remove("active");
      setActive(false);
    }
  }

  function DrawDays() {
    const Days = ["일", "월", "화", "수", "목", "금", "토"];
    return Days.map((days) => (
      <div className="days">
        <span>{days}</span>
      </div>
    ));
  }

  return (
    <div className="HeaderWrap">
      <div className="HeaderTop">
        <div className="btnBox">
          <div className="redBtn"></div>
          <div className="yellowBtn"></div>
          <div className="greenBtn"></div>
        </div>
      </div>
      <div className="HeaderMiddle">
        <div className="title">
          <span>
            {getYear}년 {getMonth}월
          </span>
        </div>
        <div className="hamber" onClick={ContainerOnOff}>
          <span className="hamberSpan"></span>
        </div>
      </div>
      <div className="HeaderBottom">
        <div className="BottomWrap">{DrawDays()}</div>
      </div>
      <Container Year={getYear} Month={getMonth} />
    </div>
  );
};

export { Header };

 

pages/Main.jsx

Header와 Footer를 불러들임

import React from "react";
import { Header } from "../components/Header";
import Footer from "../components/Footer";

const Main = () => {
  return (
    <div className="AppWrap">
      <Header />
      <Footer />
    </div>
  );
};

export default Main;

 

App.js

import "./App.css";
import Main from "./pages/Main";

function App() {
  return (
    <div className="App">
      <Main />
    </div>
  );
}

export default App;

 

index.js

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

 

우측 상단 햄버거 버튼을 누르면 아래 일수 출력

728x90

'React' 카테고리의 다른 글

[React] Redux와 OpenWeather  (1) 2023.09.14
[React] react-router-dom을 알아보기  (1) 2023.09.07
[React] Babel과 webpack 알아보기  (0) 2023.09.07
[React] React 시작하기  (3) 2023.06.28