react-calendar 라이브러리의 캘린더 View가 업데이트되지 않는 문제

YI·2023년 7월 5일
0

에러를 해결하자

목록 보기
4/4

react-calendar 라이브러리는 달력 UI과 유연한 커스터마이징을 제공하고, 날짜 범위 선택 등 다양한 기능을 제공하는 Frontend 라이브러리입니다.

회사 프로젝트 중 react-calendar 라이브러리를 사용해 검색 날짜 범위를 선택하는 기능을 개발하던 중 만난 에러와 해결 방법에 대해 이야기 해보고자 합니다.

문제 상황

react-calendar 라이브러리를 사용해 구현한 캘린더에서, 다른 달로 이동한 상태에서 “오늘로 이동하기” 버튼을 클릭했을 때, 캘린더의 화면이 현재 달로 이동하지 않는 문제가 발생했습니다.

문제가 발생하는 상황

  1. 캘린더의 네비게이션을 사용해 다음달 / 이전달 / 다음해 등으로 이동한다.
  1. value prop 값을 캘린더 외부에서 직접 변경한다. (ex. setValue(new Date()))

  2. 캘린더의 view가 value 값에 따라 업데이트되지 않는다.


문제 원인

한줄요약!

react-calendar 내부적으로 onChange 메서드에서 value 값을 가지고 activeStartDate 를 업데이트 하지 않아 발생한 문제

react-calendar의 코드를 살펴보며 조금 더 자세히 설명해보겠습니다.

react-calendar 라이브러리에서는 renderContent 메서드에서 캘린더 내부의 콘텐츠(요일,날짜 등)을 보여줍니다. 그리고 클릭 이벤트가 발생했을 때, 아래와 같이 onChange 함수를 호출합니다.

function renderContent(next?: boolean) {
    const currentActiveStartDate = next
      ? getBeginNext(view, activeStartDate)
      : getBegin(view, activeStartDate);

    const onClick = drillDownAvailable ? drillDown : onChange;

...
}

위에서 말했듯, 날짜를 클릭해 onClick 이벤트가 발생하면 결과적으로 실행되는 메서드는 아래의 onChange 메서드입니다.

onChange 메서드 내에서 보여져야할 캘린더 시작 화면을 정의하는 activeStartDate 를 갱신하는데, 이 activeStartDate을 value 값이 아닌 클릭된 캘린더 날짜인 rawNextValue 를 사용해 갱신합니다.

그렇기 때문에 value 값이 변화되어 onChange 메서드가 실행되더라도, activeStartDate는 갱신되지 않아 화면이 변경되지 않는 문제가 발생한 것 입니다.

const onChange = useCallback(
    (rawNextValue: Date, event: React.MouseEvent<HTMLButtonElement>) => {
      const previousValue = value;
			/.../
   
      let nextValue: Value;
      if (selectRange) {

        /.../

          nextValue = getValueRange(valueType, previousValue, rawNextValue);
        }
      } else {
        nextValue = getProcessedValue(rawNextValue);
      }

		// activeStartDate를 value가 아닌 클린된 날짜 값인 rawNextValue를 사용해 갱신함.
      const nextActiveStartDate =
        !selectRange ||
        isFirstValueInRange ||
        goToRangeStartOnSelect
          ? getActiveStartDate({
              maxDate,
              maxDetail,
              minDate,
              minDetail,
              value: nextValue,
              view,
            })
          : null;


		/.../
	[
      activeStartDate,
      allowPartialRange,
      getProcessedValue,
      goToRangeStartOnSelect,
      maxDate,
      maxDetail,
      minDate,
      minDetail,
      onActiveStartDateChange,
      onChangeProps,
      onClickTile,
      selectRange,
      value,
      valueType,
      view,
    ],
  );

문제 해결

한줄 요약!

value 값이 명시적으로 변경된 경우, 직접 activeStartDate를 업데이트 해줌으로써 문제를 해결

정리하자면, 캘린더에서 날짜를 클릭해 value 값을 변경하거나, navigation의 화살표를 통해 월이나 년도를 변경하면 내부적으로 activeStartDate 값이 갱신되어 캘린더의 view가 변경됩니다.

하지만 캘린더를 사용하지 않고 외부 함수로 value 값을 바꾸면 activeStartDate 이 갱신되지 않아 문제가 발생한 것 입니다.

이 문제를 외부 함수에서 value 를 갱신하는 경우에도 activeStartDate 값을 직접 업데이트 해줌으로서 문제를 해결했습니다. activeStartDateonActiveStartDateChange 라는 props를 사용해서 갱신할 수 있습니다.

const [activeStartDate, setActiveStartDate] = useState(new Date());

useEffect(() => {
    const currentActiveMonth = DateUtil.format("month", activeStartDate);
    const changedActiveMonth = DateUtil.format("month", startDate);

    if (currentActiveMonth !== changedActiveMonth) {
      setActiveStartDate(startDate);
    }
 }, [value]);

/.../

return (
	<Calendar 
		...
		value={value}
		onChange={handleOnChange}
		activeStartDate={activeStartDate}
		onActiveStartDateChange={({ activeStartDate }) =>
          setActiveStartDate(activeStartDate)
    }
	/>
)

마치며

회사에 입사 후, 항상 시간에 쫓겨 문제를 빠르게 해결하는 데만 급급해 문제가 왜 발생했는 지, 더 나은 방법은 없는지에 대한 고민을 하지 못하는 경우가 많았습니다. 그러다 보니 문제는 해결해도 개발에 대한 자신감은 오히려 떨어지는 것 같았습니다.

그래서 react-calendar 라이브러리 사용 중 만난 이 문제의 원인을 제대로 파악하고, 분석해보고자 이 글을 작성하게 되었습니다. 여러 라이브러리를 사용해 본 적이 있지만, 라이브러리 코드를 하나하나 열어보고 코드를 따라 문제의 원인을 찾아 분석해본 적은 처음이었습니다. 그래서 생각보다 원인을 찾는 일에 어려움을 겪었습니다.

하지만 이 과정을 통해 react-calendar 라이브러리를 더욱 깊게 이해할 수 있었고, 앞으로 어떤 문제를 마주했을 때 “왜 이 문제가 발생했는 지”에 대한 고민하는 것의 의미와 중요성을 배울 수 있었습니다.

마지막으로 부족하지만 같은 문제를 마주한 분이 있다면 도움이 되셨길 바라며 글을 마칩니다. 감사합니다.

Ref

https://github.com/wojtekmaj/react-calendar/issues/342
https://github.com/wojtekmaj/react-calendar/issues/358#issuecomment-634847447

profile
Junior Frontend Developer

0개의 댓글

관련 채용 정보