본문 바로가기
웹/(React)리액트

(React) 리액트 달력만들기 (초간단/쉬움)

by 공부가싫다가도좋아 2022. 5. 25.
반응형

* 본 포스팅은 직접 구현한 코드입니다. 

* 불펌 금지합니다.

* 더 좋은 코드가 있으면 가르쳐주세요 감사합니다 :)


포스팅 요약

1. 결과화면(사진 및 동영상)

2. 파일 구조

3. 코드

4. 깃허브 코드 주소


1. 결과화면 (사진 및 동영상)

1) 사진

2) 동영상

 


2. 파일 구조

 

 


3. 코드

 

경로: public/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />

    <title>달력</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

 

경로: src/App.js

import Calendar from "./component/Calendar";

function App() {
  return (
    <div>
      <Calendar />
    </div>
  );
}

export default App;

 

경로: src/component/Calendar.js

import React, { useCallback, useState } from "react";
import classNames from "classnames/bind";
import style from "../style/calendar.css";

const cx = classNames.bind(style);

const Calendar = () => {
  const today = {
    year: new Date().getFullYear(), //오늘 연도
    month: new Date().getMonth() + 1, //오늘 월
    date: new Date().getDate(), //오늘 날짜
    day: new Date().getDay(), //오늘 요일
  };
  const week = ["일", "월", "화", "수", "목", "금", "토"]; //일주일
  const [selectedYear, setSelectedYear] = useState(today.year); //현재 선택된 연도
  const [selectedMonth, setSelectedMonth] = useState(today.month); //현재 선택된 달
  const dateTotalCount = new Date(selectedYear, selectedMonth, 0).getDate(); //선택된 연도, 달의 마지막 날짜

  const prevMonth = useCallback(() => {
    //이전 달 보기 보튼
    if (selectedMonth === 1) {
      setSelectedMonth(12);
      setSelectedYear(selectedYear - 1);
    } else {
      setSelectedMonth(selectedMonth - 1);
    }
  }, [selectedMonth]);

  const nextMonth = useCallback(() => {
    //다음 달 보기 버튼
    if (selectedMonth === 12) {
      setSelectedMonth(1);
      setSelectedYear(selectedYear + 1);
    } else {
      setSelectedMonth(selectedMonth + 1);
    }
  }, [selectedMonth]);

  const monthControl = useCallback(() => {
    //달 선택박스에서 고르기
    let monthArr = [];
    for (let i = 0; i < 12; i++) {
      monthArr.push(
        <option key={i + 1} value={i + 1}>
          {i + 1}월
        </option>
      );
    }
    return (
      <select
        onChange={changeSelectMonth}
        value={selectedMonth}
      >
        {monthArr}
      </select>
    );
  }, [selectedMonth]);

  const yearControl = useCallback(() => {
    //연도 선택박스에서 고르기
    let yearArr = [];
    const startYear = today.year - 10; //현재 년도부터 10년전 까지만
    const endYear = today.year + 10; //현재 년도부터 10년후 까지만
    for (let i = startYear; i < endYear + 1; i++) {
      yearArr.push(
        <option key={i} value={i}>
          {i}년
        </option>
      );
    }
    return (
      <select
        // className="yearSelect"
        onChange={changeSelectYear}
        value={selectedYear}
      >
        {yearArr}
      </select>
    );
  }, [selectedYear]);

  const changeSelectMonth = (e) => {
    setSelectedMonth(Number(e.target.value));
  };
  const changeSelectYear = (e) => {
    setSelectedYear(Number(e.target.value));
  };

  const returnWeek = useCallback(() => {
    //요일 반환 함수
    let weekArr = [];
    week.forEach((v) => {
      weekArr.push(
        <div
          key={v}
          className={cx(
            { weekday: true },
            { sunday: v === "일" },
            { saturday: v === "토" }
          )}
        >
          {v}
        </div>
      );
    });
    return weekArr;
  }, []);

  const returnDay = useCallback(() => {
    //선택된 달의 날짜들 반환 함수
    let dayArr = [];

    for (const nowDay of week) {
      const day = new Date(selectedYear, selectedMonth - 1, 1).getDay();
      if (week[day] === nowDay) {
        for (let i = 0; i < dateTotalCount; i++) {
          dayArr.push(
            <div
              key={i + 1}
              className={cx(
                {
                  //오늘 날짜일 때 표시할 스타일 클라스네임
                  today:
                    today.year === selectedYear &&
                    today.month === selectedMonth &&
                    today.date === i + 1,
                },
                { weekday: true }, //전체 날짜 스타일
                {
                  //전체 일요일 스타일
                  sunday:
                    new Date(
                      selectedYear,
                      selectedMonth - 1,
                      i + 1
                    ).getDay() === 0,
                },
                {
                  //전체 토요일 스타일
                  saturday:
                    new Date(
                      selectedYear,
                      selectedMonth - 1,
                      i + 1
                    ).getDay() === 6,
                }
              )}
            >
              {i + 1}
            </div>
          );
        }
      } else {
        dayArr.push(<div className="weekday"></div>);
      }
    }

    return dayArr;
  }, [selectedYear, selectedMonth, dateTotalCount]);

  return (
    <div className="container">
      <div className="title">
        <h3>
          {yearControl()}년 {monthControl()}월
        </h3>
        <div className="pagination">
          <button onClick={prevMonth}>◀︎</button>
          <button onClick={nextMonth}>▶︎</button>
        </div>
      </div>
      <div className="week">{returnWeek()}</div>
      <div className="date">{returnDay()}</div>
    </div>
  );
};

export default Calendar;

 

경로: src/style/calendar.css

button {
  cursor: pointer;
}

.container {
  width: 500px;
  height: 400px;
  margin: auto;
  padding: 20px 20px;
  border: 1px solid rgba(128, 128, 128, 0.267);
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

.container .title {
  display: flex;
}

.container .title > button {
  border: none;
  margin-left: 5px;
  height: 20px;
  align-self: center;
  background: none;
}

.container .title .pagination {
  margin-left: auto;
  align-self: center;
}
.container .title .pagination button {
  margin: 0 10px;
  border: none;
  background: none;
}

.container .week {
  display: flex;
}

.container .week .weekday {
  width: calc(500px / 7);
  text-align: center;
}

.container .week .sunday {
  color: red;
}

.container .week .saturday {
  color: blue;
}

.container .date {
  margin-top: 20px;
}

.container .date .weekday {
  width: calc(500px / 7);
  float: left;
  text-align: center;
  height: 50px;
  line-height: 50px;
}

.container .date .sunday {
  color: red;
}

.container .date .saturday {
  color: blue;
}

.container .date .today {
  background-color: rgb(88, 111, 187);
  color: white;
  font-weight: 700;
  border-radius: 50%;
}

 

경로: ./package.json

{
  "name": "calendar",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/react": "^13.2.0",
    "@testing-library/user-event": "^13.5.0",
    "classnames": "^2.3.1",
    "react": "^18.1.0",
    "react-dom": "^18.1.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

4. 깃허브 코드 주소

https://github.com/6810779s/calendar

 

GitHub - 6810779s/calendar

Contribute to 6810779s/calendar development by creating an account on GitHub.

github.com

 

반응형

댓글