캘린더 본문을 만들기 위해, 컴포넌트간 데이터 전달이 필요해졌다.
지금 만들고 있는 캘린더는 전체가 캘린더라는 커다란 컴포넌트로 감싸져 있고, 그 아래 헤더(해당월 지정하는 부분)와 바디(달력 본문)라는 두 개의 컴포넌트가 들어온다.
function Calendar() {
return (
<div className="calWrapper">
<Header />
<Body />
</div>
);
}
export default Calendar;
이 때 헤더에서 달력의 월을 앞뒤로 전환하면, 이를 바디로 전달해야 한다. 즉, 자식 컴포넌트에서 다른 자식 컴포넌트로 데이터를 전달해야 한다. 이를 위해, 헤더(자식) -> 캘린더(부모) -> 바디(자식) 순으로 데이터를 전달하고자 한다.
리액트의 컴포넌트는 클래스형과 함수형으로 나뉜다. 컴포넌트간 데이터 전달을 검색해보면 주로 클래스형 컴포넌트의 경우를 소개한다. 함수형으로 사용하기 위해서는 useState
라는 Hook을 활용해준다.
const [baseDate, setBaseDate] = useState(moment());
useState
를 이용해 baseDate
라는 변수를 정의했다.setBaseDate
이다. return (
<div className="calWrapper">
<Header setBaseDate={ setBaseDate } />
</div>
);
setBaseDate
를 자식 컴포넌트로 전달한다.setBaseDate
함수를 동작시켜, 변경된 정보를 부모의 baseDate
로 설정하고자 한다.function Calendar(props) {
return (
<div className="calHeaderWrapper">
<div className="calHeaderBtn calHeaderBeforeBtn">
<LeftOutlined
style={{ color: "#EFBF43"}}
onClick={() => {
setCurDate(curDate.add(1, 'months'));
props.setBaseDate(curDate);
}}
/>
</div>
</div>
);
}
export default Calendar;
curDate
가 변경되는데, 이를 setBaseDate
에 넣어 부모 컴포넌트로 전달한다.function Calendar() {
const [baseDate, setBaseDate] = useState(moment());
return (
<div className="calWrapper">
<Header setBaseDate={ setBaseDate } />
<Body baseDate={ baseDate } />
</div>
);
}
이렇게 헤더에서 설정된 baseDate
를 부모 컴포넌트인 Calendar를 경유하여, 형제(?) 컴포넌트인 바디로 전달할 수 있다.
이 과정에서 세 가지 의문점이 발생했다. 여러가지로 살펴보았으나 해결하지 못해서 나중을 위해 적어둔다.
즉, 하나의 변수는 한 개의 자식 컴포넌트에만 전달할 수 있다.
return (
<div className="calWrapper">
<Header baseDate={ baseDate } />
<Body baseDate={ baseDate } />
</div>
);
baseDate
를 문제 없이 전달받았으나, Body에서는 props.baseDate
를 확인하면 undefined가 발생했다.baseDate
를 헤더로 전달하지 않고 바디로 바로 전달하자 문제 없이 전달받을 수 있었다.코딩을 잘못 한 것인지, 리액트가 원래 이런 식으로 작동하는 것인지는 알 수 없지만 이를 염두에 두고 컴포넌트를 기획해야겠다.
<Header baseDate={ baseDate } setBaseDate={ setBaseDate } />
baseDate
와 setBaseDate
를 모두 전달받았다. baseDate
를 curDate
의 초기값으로 설정하고, setCurDate
로 변경한 뒤, setBaseDate
를 이용해 부모로 전달하려고 시도했다.리액트에서 복수의 props를 사용하는 것이 가능하기 때문에 전달 과정에서의 문제는 아닌 것 같은데, 어디에서 state 변경이 잘못 된 것인지 이유를 알 수 없었다. 우선은 초기값을 다시 설정하는 것으로 넘어갔다.
const curDate = props.baseDate
const firstDateOfMonth = curDate.startOf('month')
baseDate
를 받아온 다음,startOf
메소드를 사용해 그 달의 첫 날을 구하고자 한다.moment()
로 주어진 baseDate
가 2021년 3월 23일이라면, curDate
는 2021년 3월 23일이며,startOf
를 적용한 firstDateOfMonth
는 2021년 3월 1일로 설정되어야 한다. curDate
까지도 3월 1일로 저장되는 이상한 현상이 발생했다. const curDate = props.baseDate
const firstDateOfMonth = curDate.clone().startOf('month')
clone()
메소드로 curDate
와 firstDateOfMonth
를 분리하는 데 성공했다.당장 캘린더를 구현하는 데 큰 지장은 없을 것 같아서 우선은 넘어가는 내용들이지만, 나중에 리액트를 좀 더 이해하고 공부하며 다시 짚어보고 싶은 내용이라 기록해 둔다.