달력의 날짜 배열을 생성할 때, object 형식으로 만들어주었다.
ex) [{day: '21', beforeDay=false}, {day: '22', beforeDay=false}, ...]
그리고 각 월마다 시작하는 요일은 다르기 때문에 unshift 방식을 이용하여 빈 공간을 채워주었는데 이렇게 되면 undefined 값을 가지기 때문에 key값에 접근할 때 오류가 나게 되었다.
arr.unshift(...new Array(firstDay))
하지만 object 형식으로 빈 공간을 채워준다면 존재하지 않는 key값이더라도 undefined 값을 리턴
하기 때문에 오류가 뜨지 않는다.
// 변경된 방식
arr.unshift(...new Array(firstDay).fill(0).map((v, i) => ({})));
메인페이지 기준으로 체크인, 체크아웃을 할 수 있게 변경하였다.
이를 위해서는 다음과 같은 조건들이 필요했다.
해당 경우는 달력의 배열을 만들 때 day날짜는 공백으로 만들어놨기 때문에 쉽게 판단할 수 있었다.
// Calendar.js
<div
data-dateformat={`${monthData.year}-${monthData.month}-${date.day}`}
css={dateBtn({ date })}
key={`${monthData.year} + ${i}`}
onClick={e => handleDatePick(e.target, date.beforeDay)}
>
{date.day}
</div>
// CalendarContainer.js
const handleDatePick = (target, beforeDay) => {
const pickedDate = target.dataset.dateformat.split('-');
const day = pickedDate[2];
if (day === 'undefined') return; // 공백인 칸
};
해당 경우도 마찬가지로 이전 날짜에 대해서도 boolean 값으로 저장이 되어있어 판단할 수 있었다.
// Calendar.js
<div
data-dateformat={`${monthData.year}-${monthData.month}-${date.day}`}
css={dateBtn({ date })}
key={`${monthData.year} + ${i}`}
onClick={e => handleDatePick(e.target, date.beforeDay)}
>
{date.day}
</div>
// CalendarContainer.js
const handleDatePick = (target, beforeDay) => {
/* 생략... */
if (beforeDay) return; // 이전 날짜
};
우선, 체크인 날짜를 설정해야 체크아웃이 될 수 있게 하였다.
체크아웃을 설정할 때 기존의 체크인은 timeStamp형식으로 저장되어있기 때문에 체크아웃을 할 날짜와 체크인의 날짜를 비교하여 앞서게 되면 그 날짜를 체크인 날짜로 변경하는 방식으로 해주었다.
const handleDatePick = (target, beforeDay) => {
/* 생략... */
const timeStamp = new Date(`${pickedDate[0]}-${padding(pickedDate[1])}-${padding(pickedDate[2])}`,
);
if (!checkInDay || timeStamp < checkInDay) {
console.log('체크인 날짜 설정...');
changeCheckInOutDay('checkIn', timeStamp);
} else {
console.log('체크아웃 날짜 설정...');
changeCheckInOutDay('checkOut', timeStamp);
}
};
위에서 사용된 const timeStamp = new Date('2021-10-01');
은 아래와 같은 결과를 얻게 되며 Date객체의 메서드를 사용할 수 있기 때문
에 timeStamp 형식으로 관리한다면 유용하게 쓸 수 있다.
또 검색창에 장소를 검색할 때 느려진다...
확인해보니까 기존의 원인이였던 SingleCalendar 컴포넌트
가 불필요한 리렌더링을 하고있었다.
이유는 리렌더링시마다 새로 생성되는 상위 컴포넌트의 함수때문
이였다.
<Calendar
leftMonth={leftMonth}
rightMonth={rightMonth}
setMonth={setMonth}
handleDatePick={handleDatePick}
/>
위에서 새로 추가한 handleDatePick함수가 리렌더링시마다 새로 생성되었기 때문에 이 함수를 건네받는 하위 컴포넌트인 SingleCalendar 컴포넌트
는 값이 변경되었다고 인식을 하여 불필요한 리렌더링을 하고 있었다.
그렇다면 이번에는 리렌더링시 불필요한 함수가 재생성되는것을 방지해야 하는데 이는 useCallback
을 이용하면 된다.
useMemo
는 값을 반환하는 반면 useCallback
은 함수를 반환하기 때문에 함수를 재활용하는 목적으로써 useCallback
를 사용했다.
const handleDatePick = useCallback(
(target, beforeDay) => {
const pickedDate = target.dataset.dateformat.split('-');
const timeStamp = new Date(
`${pickedDate[0]}-${padding(pickedDate[1])}-${padding(pickedDate[2])}`,
);
const day = pickedDate[2];
if (beforeDay) return;
if (day === 'undefined') return;
if (!checkInDay || timeStamp < checkInDay) {
console.log('체크인 날짜 설정 중');
changeCheckInOutDay('checkIn', timeStamp);
} else {
console.log('체크아웃 날짜 설정 중');
changeCheckInOutDay('checkOut', timeStamp);
}
},
[checkInDay, checkOutDay],
);
여기서 useMemo
와 동일하게 두번째 인자의 의존성 상태값을 주의하며 사용해야 하며 useCallback
를 사용하고나니 원하는 결과를 얻을 수 있게 되었다.