Skip to content

Latest commit

 

History

History
219 lines (145 loc) · 5.04 KB

220812.md

File metadata and controls

219 lines (145 loc) · 5.04 KB

리액트로 캘린더 만들기

reactmoment.js 그리고 styled-component를 이용하여 캘린더를 만들어 보도록 하겠다.


moment.js

공식문서

  • JS 기본 제공 함수인 Date()와 비슷하지만 더 편리하게 사용 할 수 있는 날짜,시간 라이브러리이다.
  • moment()라는 함수를 사용하며 리턴 값으로 날짜와 method들이 담겨있는 객체를 반환한다.

  • 설치 방법
npm install moment --save 
yarn add moment  

moment()

  • 기본 적으로 호출시 현재의 시간을 담은 객체를 리턴한다.
console.log(moment())

image-20220812182658679

  • 인자로 string 형태의 날짜를 넣어주면, 그 날짜를 담은 객체를 리턴해 준다.
console.log(moment("2019-05-11"))

image-20220812182852348


.clone()

moment()객체에 method를 쓸 경우 원본 값이 바뀌기 때문에 복제해서 원본을 유지하는 역활을 한다.

moment().clone()

.format()

인자로 날짜의 형식을 받아서 moment()객체를 문자열로 출력해준다.

console.log(moment().format("YYYY-MM"));
// 2022-08
console.log(moment().format("YYYY-MM-DD"));
// 2022-08-12
console.log(moment().format("MM-DD"));
// 08-12
console.log(moment().format("DD-MM"));
// 12-08

.startOf() .endOf()

moment()객체를 기준으로 인자로 받은 단위 기간의 처음과 끝을 알려준다.

ex) 오늘 기준 이번달의 첫날

console.log(moment().clone().startOf("month").format("YYYY-MM-DD"));
// 2022-08-01

ex) (오늘 기준 이번달의 첫날)을 기준으로 이번주의 첫날

console.log(moment().clone().startOf("month").startOf("week").format("YYYY-MM-DD"));
// 2022-07-31

.isBefore() .issame() .isAfter()

moment()객체를 기준으로 첫번째 인자와의 대소를 비교한다. 두번째 인자로는 비교할 단위를 받는다.

// endDay가 지금보다 이전인지 date단위로 비교
moment().isBefore(endDay, "day")
// endDay가 지금이랑 같은 달인지 month단위로 비교
moment().isSame(endDay, "month")

.add() .subtract()

moment()객체를 기준으로 첫번째 인자로 받은 값 만큼 두번째 인자 단위로 빼거나 더한다.

//오늘 보다 일주일 후
moment().add(1, "week")

//오늘 보다 3일 전
moment().subtract(3, "day")


달력에서 보여 줄 한달간의 날짜 목록 만들기

앞서 배운 moment.js를 활용하면 오늘을 기준으로 이번달의 첫날과 마지막 날을 구할 수 있다.

moment().clone().startOf("month")
// 2022-08-01
moment().clone().endOf("month")
// 2022-08-31

하지만 달력에서는 이번달 뿐만일 아니라 첫날과 끝날이 속한 week의 날짜들을 전부 표시해줘야된다. 그렇다면 위에 코드에 .startOf("week").endOf("week")를 추가해 보자

const startDay = moment().clone().startOf("month").startOf("week")
// 2022-07-31
const endDay = moment().clone().endOf("month").endOf("week")
// 2022-09-03

자 이제 이번달에 보여 줄 날짜들을 달력으로 만들기 좋게 2차원 리스트로 만들어보자

[week , week, week, week, ...]의 형식으로

const day = startDay.clone().subtract(1, "day");

while (day.isBefore(endDay, "day")) {
    calendar.push(
      Array(7)
        .fill(0)
        .map(() => day.add(1, "day").clone())
    );
  }
  • 달력의 처음 날짜인 startDay 보다 하루 전을 day라고 지정한 후
  • dayendDay 가 될때 까지 while 문을 돌려보자
  • Array(7) 7개의 원소로 이루어진 week 배열을 0으로 채운 뒤 각각의 위치에 day의 값을 1일 씩 더해서 채워 준다.
  • 결과 적으로 달력의 형태를 가진 2차원 배열이 만들어진다.

image-20220812185803066

위의 코드를 build.js라는 로직으로 분리해 놓겠다.

//build.js

const buildCalendar = (value) => {
  const startDay = value.clone().startOf("month").startOf("week");
  const endDay = value.clone().endOf("month").endOf("week");
  const day = startDay.clone().subtract(1, "day");
  const calendar = [];
  while (day.isBefore(endDay, "day")) {
    calendar.push(
      Array(7)
        .fill(0)
        .map(() => day.add(1, "day").clone())
    );
  }
  return calendar;
};

export default buildCalendar;

이제 배열을 view상에 분배 해 보자

{calendar.map((week, w) => (
  <Weeks key={"week" + w}>
    {week.map((day, d) => (
      <Day
        day={day}
        value={value}
        events={events}
        onChange={click ? onChange : () => {}}
        key={"day" + w + d}
      />
    ))}
  </Weeks>
))}