뭐부터 써야할지 모르겠으니 기능을 차근차근 적어봐야겠다..
내가 처음에 구현한 것은 조회기간 설정 부분이다.
전부 내가 한 것은 아니고, 팀장님께서 많이 도와주셨다.
그래서 복습 겸 코드 분석 겸 정리해보고자 한다.
우선 앞 부분의 날짜를 기본 날짜의 전 달 기준으로 처리해야했다.
여기서 moment()를 처음으로 써 봤다.
// 기본 날짜 전달 기준 처리
let defaultDate = new Date(moment().format('YYYY-MM'));
const diff = moment(defaultDate).format('DD');
if (Number(diff) < 10) {
defaultDate = new Date(moment().subtract(1, 'months').format('YYYY-MM'));
}
defaultDate 라는 변수를 만든다.
1-1. moment()를 사용한 새로운 객체를 만든다.
1-2. format('YYYY-MM') = '2023-01' 형식으로 나타낸다.
test 라는 변수를 만든다.
--> 기획서 상에서, 당월 기준 10일 이전이면 전달로 처리하고
10일 이후라면 당월로 처리해야하라고 적혀있기 때문에 만듦
defaultData의 DD (test) 가 10보다 작으면
3-1. 새로운 defaultData를 만듦
3-2. subtract(1, months) = 기준 일자 1달 전
타입스크립트여서 자료형을 선언해줘야한다.
FormDateLayout 라는 component를 만들어서 styled-components로 스타일을 만들어준다.
import * as React from 'react';
import styled from 'styled-components';
import moment from 'moment';
export interface IFormDate {
value?: any;
type?: string;
defaultValue?: string;
className?: string;
name?: string;
id?: string;
min?: string;
max?: string;
onChange: (e) => void;
}
const FormDateLayout = styled.div`
.input_date {
background-image: url('/img/calendar_12cm_icon.png');
background-size: 14px;
font-size: 14px;
font-weight: 400;
letter-spacing: 0em;
text-align: left;
}
.cm_input_date {
width: 100%;
max-width: 138px;
height: 40px;
padding: 11px;
border: 1px solid #dbdbdb;
border-radius: 3px;
-webkit-appearance: none;
-moz-appearance: none;
background-repeat: no-repeat;
background-position-x: 93%;
background-position-y: 50%;
background-color: #ffffff;
cursor: pointer;
/* background-image: url(/img/icon-calendar.png); */
position: relative;
}
.cm_input_date::-webkit-calendar-picker-indicator {
background: transparent;
z-index: 1;
width: 100%;
height: 100%;
position: absolute;
cursor: pointer;
}
`;
const FormDate: React.FC<IFormDate> = ({
value,
className,
name,
id,
type,
defaultValue,
min,
max,
...props //이거 넣어야 이벤트 되넹 ㅎㅎ
}: IFormDate) => {
return (
<FormDateLayout>
<input
value={value ? moment(value).format('YYYY-MM') : defaultValue}
type={type ? type : 'date'}
name={name}
id={id}
defaultValue={defaultValue}
className={`input_date cm_input_date hp_mr-30 ${className}`}
min={min}
max={max}
{...props}
/>
</FormDateLayout>
);
};
export default FormDate;
IFormDate 내부의 onChange: (e) => void;
3. 그리고 향후 활용할 FormDate를 만든다.
< 단점 >
- children을 암시적으로 가지고 있다.
- 제네릭을 지원하지 않는다.
- 네임 스페이스 패턴을 이용할 때 더 불편하다.
- FC를 이용하면 코드가 더 길어진다
라는 단점으로 인해 React 18 이상부터 없어졌다!
하지만 우리는 활용했다...ㅋㅋ
보통 단점을 인지하고 있으면서도 활용하는 이유는, 편하고 익숙하기 때문이라고 한다.
명확하게 이해는 못했지만,
특정 태그에서 기본적으로 사용 가능한 값들을 의미하는 것이 아닐까?
{...props}를 첨부하지 않으면
onClick/onChange => (e) => 에서
내가 선언한 onChange 이용이 불가했다.
{...props}라는 속성을 첨부하니, 이벤트가 정상적으로 작동했다.
params는 백엔드에서 요청한 request 값들이다.
만들어둔 defaultData를 활용해 FormDate에 적용한다.
<FormDate
type="month"
id="startDateId"
value={params.strtDt}
max={moment(defaultDate).format('YYYY-MM')}
onChange={(e) => {
setParams({ ...params, strtDt: moment(e.target.value).format('YYYYMM') });
}}
/>
<span className="hp_mr-15 hp_ml-15 un_wave">{' ~ '}</span>
<FormDate
type="month"
id="endDateId"
value={params.endDt}
min={params.strtDt}
max={moment(defaultDate).format('YYYY-MM')}
onChange={(e) => {
setParams({ ...params, endDt: moment(e.target.value).format('YYYYMM') });
}}
/>
onClick에 setter를 넣으며 마무리!