์ƒˆ์†Œ์‹

Project : Together Sports

[์›น ํ”„๋กœ์ ํŠธ] ๋ฆฌ์•กํŠธ datepicker ์ง์ ‘ ๊ตฌํ˜„ํ•˜๊ธฐ

  • -
728x90

๐ŸŽˆ ์ง์ ‘ ๊ตฌํ˜„ํ•˜๋Š” ์ด์œ ?

๋ฆฌ์•กํŠธ์—์„œ๋Š” ๋ณดํ†ต react-datepicker๋ผ๋Š” ๊ธฐ์กด์— ์ž˜ ๋งŒ๋“ค์–ด์ง„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค.

ํ•˜์ง€๋งŒ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ, ์›ํ•˜๋Š” ๋””์ž์ธ ๋Œ€๋กœ๋งŒ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์€ ๋‹ค์†Œ ๋ฒˆ๊ฑฐ๋กญ๋‹ค.

๋•Œ๋ฌธ์— ๋‚˜๋Š” ์–ธ์ œ๋“  ์›ํ•˜๋Š” ๊ธฐ๋Šฅ๊ณผ ๋””์ž์ธ์œผ๋กœ ์ˆ˜์ •์„ ์šฉ์ดํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋„๋ก datepicker๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•ด ๋ณด์•˜๋‹ค.

 

๐Ÿ“ข ๊ตฌํ˜„ ์ค‘ ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ

1. ๋จผ์ € moment๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•ด ์•Œ์•„๋‘์–ด์•ผ ํ•œ๋‹ค.
์ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋‹ฌ๋ ฅ์— ํ‘œ์‹œ๋˜๋Š” ์š”์ผ ๋“ฑ์„ ๋Œ€์‹  ๊ณ„์‚ฐํ•ด์ค€๋‹ค.
์ด ๊ณ„์‚ฐ ๋˜ํ•œ ์ง์ ‘ํ•˜๋ ค๋ฉด ํ•ด๋‹น ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ด์šฉํ•ด์„œ ๊ตฌํ•  ์ˆ˜ ์žˆ์œผ๋‚˜ ์—ฌ๊ธฐ์„œ๋Š” moment๋ฅผ ์ด์šฉํ•˜์˜€๋‹ค.

2. ์„ ํƒ๋œ ๋‚ ์งœ๋‚˜ ํ˜„์žฌ ๋‹ฌ๋ ฅ์— ํ‘œ์‹œ๋˜๋Š” ์—ฐ๋„ ๋“ฑ์„ useState๋ผ๋Š” ๋ฆฌ์•กํŠธ ํ›…์„ ์ด์šฉํ•˜์—ฌ ๊ด€๋ฆฌํ•œ๋‹ค.
( * ๋ณ€๊ฒฝ ์‹œ render๋˜๋„๋ก )

3. ํด๋ฆญ ์ด๋ฒคํŠธ๋กœ target.classList๋ฅผ ์ด์šฉํ•˜์—ฌ UI๋ฅผ ์ˆ˜์ •ํ•œ๋‹ค.

 

๐Ÿ“ข ๊ตฌํ˜„ ๊ณผ์ • ( ํ•ต์‹ฌ์ ์ธ ๋กœ์ง๋งŒ )

  // ํ˜„์žฌ ํ•ด๋‹นํ•˜๋Š” ๋…„๋„ ๋ฐ ๋‹ฌ
  const [curYear, setCurYear] = useState(moment().year());
  const [curMonth, setCurMonth] = useState(moment().month());
  
  // ํ•ด๋‹นํ•˜๋Š” ๋‹ฌ์˜ day ์ˆ˜
  const allDaysOfMonth = moment([curYear, 0, 31]).month(curMonth).format("DD");

  // ํ•ด๋‹น ๋‹ฌ ์ฒซ 1์ผ์˜ ์š”์ผ
  const firstDayOfCurMonth = moment([curYear, curMonth, 1]).day();

  // ํ•ด๋‹น ๋‹ฌ ๋งˆ์ง€๋ง‰ ์š”์ผ
  const lastDayOfCurMonth = moment([curYear, curMonth, allDaysOfMonth]).day();

  // ์ง€๋‚œ ๋‹ฌ ๋งˆ์ง€๋ง‰ ๋‚ ์งœ
  const lastDateOfLastMonth = moment([curYear, 0, 31])
    .month(curMonth - 1)
    .format("DD");

  // ์ง€๋‚œ ๋‹ฌ์— ๋ณด์—ฌ์ ธ์•ผํ•˜๋Š” day๋“ค
  const preCalendarDays = [];

  // ํ•ด๋‹น ๋‹ฌ
  const curCalendarDays = [];

  // ๋‹ค์Œ ๋‹ฌ
  const nextCalendarDays = [];

  // ๋ณด์—ฌ์ ธ์•ผํ•˜๋Š” ์ง€๋‚œ ๋‹ฌ ์ˆ˜
  if (firstDayOfCurMonth > 0) {
    for (let i = 0; i < firstDayOfCurMonth; i++) {
      preCalendarDays.push(lastDateOfLastMonth - firstDayOfCurMonth + i + 1);
    }
  }

  // ๋ณด์—ฌ์ ธ์•ผํ•˜๋Š” ํ•ด๋‹น ๋‹ฌ ์ˆ˜
  for (let i = 1; i <= allDaysOfMonth; i++) {
    curCalendarDays.push(
      `${curYear}-${String(curMonth + 1).padStart(2, 0)}-${i}`
    );
  }

  // ๋ณด์—ฌ์ ธ์•ผํ•˜๋Š” ๋‹ค์Œ ๋‹ฌ ์ˆ˜
  for (let i = 1; i < 7 - lastDayOfCurMonth; i++) {
    nextCalendarDays.push(`${i}`);
  }

์ฃผ์„์ฒ˜๋Ÿผ moment๋ฅผ ์ด์šฉํ•ด ๊ฐ๊ฐ์˜ ๊ฐ’์„ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

ํ•ด๋‹น ๋ณ€์ˆ˜๋“ค์„ pre, cur, next ๋ฐฐ์—ด์„ ํ†ตํ•ด ๋‚ ์งœ๋ฅผ ๋‹ด๋Š” ์ด์œ ๋Š” ํ•ด๋‹น ๋‹ฌ์„ ๋ณด๋”๋ผ๋„

์ด์ „ ๋‹ฌ์˜ ๋งˆ์ง€๋ง‰ ๋‚ ์งœ์™€ ๋‹ค์Œ ๋‹ฌ์˜ ์ฒ˜์Œ ๋‚ ์งœ๋ฅผ ํ‘œ์‹œํ•ด์ฃผ๋Š”๊ฒŒ ์‚ฌ์šฉ์ž ์ธก๋ฉด์—์„œ ๋” ์ง๊ด€์„ฑ์žˆ๊ณ ,

์ด๋ฅผ ๋ Œ๋”์‹œํ‚ฌ ๋•Œ, ๊ตฌ๋ถ„์ง€์–ด UI๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
( ๋‹ค ๋”ฐ๋กœ ํƒœ๊ทธ๋ฅผ ๋‹ฌ์•„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์„ ์•Œ์•„์•ผ ํ•œ๋‹ค. )

๊ทธ๋Ÿผ ์œ„์™€ ๊ฐ™์ด 27, 28 ๋”ฐ๋กœ 1~31 ๋”ฐ๋กœ 1~2 ๋”ฐ๋กœ ๋ Œ๋”๋งํ•˜์—ฌ ์ง๊ด€์ ์œผ๋กœ ๋ณด์ด๊ฒŒ ํ•œ๋‹ค.

ํ™”๋ฉด์— ๋ณด์—ฌ์ง€๋Š” ํ•ต์‹ฌ ํ‹€์€ ๋งŒ๋“ค์—ˆ์œผ๋‹ˆ, ์ด์ œ ๋‹ค๋ฅธ ๋…„๋„์™€ ๋‹ฌ์„ ๋ณด๋”๋ผ๋„ ๋ฐ”๋€Œ๋„๋ก ์„ค์ •ํ•ด์•ผํ•œ๋‹ค.

๋จผ์ € ๋‘ ๊ฐ€์ง€ ์ •๋„๋ฅผ ๊ณ ๋ คํ•ด ๋ณด์•˜๋‹ค.

1. ๋‹ฌ๋ ฅ์˜ ์™ผ์ชฝ, ์˜ค๋ฅธ์ชฝ ํ‘œ์‹œ๋ฅผ ํด๋ฆญํ•ด์„œ ์ด๋™ํ•˜๋„๋ก

2. ์ด์ „ ๋‹ฌ ๋˜๋Š” ๋‹ค์Œ ๋‹ฌ์˜ ์ผ์ž๋ฅผ ํด๋ฆญํ•˜๋ฉด ์ด๋™๋˜๋„๋ก


1๋ฒˆ์˜ ๊ฒฝ์šฐ์—๋Š” ๋งค์šฐ ๊ฐ„๋‹จํ•˜๋‹ค. ์™ผ์ชฝ์œผ๋กœ ๊ฐˆ ์‹œ์—๋Š” ์˜ˆ๋ฅผ๋“ค์–ด 2022๋…„ 1์›”์—์„œ 2021๋…„ 12์›”๋กœ ๋„˜์–ด๊ฐ€๋Š” ์ƒํ™ฉ๋งŒ
์ž˜ ๊ณ„์‚ฐํ•ด์ฃผ๋ฉด ๋œ๋‹ค. ์˜ค๋ฅธ์ชฝ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋‹ค.

// ์ด์ „ ๋‹ฌ ์ด๋™
  const checkPreCalendar = () => {
    if (curMonth === 0) {
      setCurYear(curYear - 1);
      setCurMonth((curMonth = 11));
      return;
    }
    setCurMonth(curMonth - 1);
  };

  // ๋‹ค์Œ ๋‹ฌ ์ด๋™
  const checkNextCalendar = () => {
    if (curMonth === 11) {
      setCurYear(curYear + 1);
      setCurMonth((curMonth = 0));
      return;
    }
    setCurMonth(curMonth + 1);
  };


๊ธฐ๋ณธ ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ useState๋ฅผ ์ด์šฉํ•˜๋Š” ๋‹ฌ์„ - ๋˜๋Š” + ํ•ด์ฃผ๊ณ  ์œ„์— ์–ธ๊ธ‰ํ•œ ์˜ˆ์™ธ์ƒํ™ฉ๋งŒ ๊ณ ๋ คํ•ด์ฃผ์—ˆ๋‹ค.
์ดํ›„ ๋ฒ„ํŠผ์„ ๋งŒ๋“ค์–ด ๊ฐ๊ฐ์˜ event๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.


2๋ฒˆ์˜ ๊ฒฝ์šฐ์—๋Š” ์ด์ „ ๋‹ฌ์„ ํด๋ฆญํ•œ ๊ฒƒ์ธ์ง€, ๋‹ค์Œ ๋‹ฌ์„ ํด๋ฆญํ•œ ๊ฒƒ์ธ์ง€, ์•„๋‹ˆ๋ฉด ํ•ด๋‹นํ•˜๋Š” ๋‹ฌ์„ ํด๋ฆญํ•˜๋Š” ๊ฒƒ์ธ์ง€ ๋ถ„๋ณ„์ด ํ•„์š”ํ•˜๋‹ค.

๋‚˜ ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” ๋ Œ๋” ์‹œ className์„ 

// pre
className={`special-days-in-grid left`}

// current
className={`days-in-grid ${curYear}-${curMonth + 1}-${index + 1}`}

// next
className={`special-days-in-grid right`}

์„ ํ†ตํ•˜์—ฌ ์ฐจ๋ณ„์„ ์ฃผ์—ˆ๊ณ , ํด๋ฆญ์‹œ e.target.classList์˜ ๊ฐ’์„ ํ†ตํ•ด ํŠธ๋ฆฌ๊ฑฐ๋ฅผ ๊ตฌ๋ถ„์ง€์—ˆ๋‹ค.

๊ทธ ์ดํ›„๋Š” 1๋ฒˆ์˜ ๊ฒฝ์šฐ์™€ ๋˜‘๊ฐ™๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.



๋งˆ์ง€๋ง‰์œผ๋กœ ์ œ์ผ ์ค‘์š”ํ•œ ๊ฒƒ์€ ์š”์ผ์„ ์„ ํƒํ•  ๋•Œ์˜ ์ฒ˜๋ฆฌ์˜€๋‹ค.

์š”์ผ์„ ์„ ํƒํ•˜๋Š” ๊ฒƒ์€ ์ด์ „ ๋‹ฌ์˜ ์š”์ผ์„ ํด๋ฆญํ•˜์—ฌ๋„ ์ด์ „ ๋‹ฌ๋กœ ๋„˜์–ด๊ฐ€์„œ ํ•ด๋‹นํ•˜๋Š” ์š”์ผ์ด ์„ ํƒ๋˜์–ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์ด ํ•ต์‹ฌ์€ ์œ„์˜ current์— ๋ Œ๋” ์‹œ ํ•ด๋‹นํ•˜๋Š” ์š”์ผ์„ className์— ๋„ฃ์–ด๋‘๊ณ ,

  // ์„ ํƒ๋œ ๋‚ 
  const [curSelectedDate, setCurSelectedDate] = useState();

์œ„์™€ ๊ฐ™์ด ์„ ํƒ๋œ ๋‚ ์„ useState๋ฅผ ํ†ตํ•ด ์ €์žฅํ•ด์„œ, ๋ Œ๋” ์‹œ ์„ ํƒ๋œ ๋‚ ์ผ๋•Œ๋งŒ clicked ๋ผ๋Š” className์„ ์ฃผ์–ด ํ‘œ์‹œํ•œ๋‹ค.

๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์™„์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

์ถ”๊ฐ€ ๊ธฐ๋Šฅ์ด ์ƒ๊ธด๋‹ค๋ฉด ์–ธ์ œ๋“  ํŽธํ•˜๊ฒŒ ๊ตฌํ˜„ํ•ด์„œ ๋„ฃ์œผ๋ฉด ๋!

์‹œ์—ฐ ์˜์ƒ

 

Contents

ํฌ์ŠคํŒ… ์ฃผ์†Œ๋ฅผ ๋ณต์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค

์ด ๊ธ€์ด ๋„์›€์ด ๋˜์—ˆ๋‹ค๋ฉด ๊ณต๊ฐ ๋ถ€ํƒ๋“œ๋ฆฝ๋‹ˆ๋‹ค.