-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
230630_KDT5_TEAM3_3조 과제 최종 제출 #3
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
늦게까지 함께 모여서 코딩하시는 모습 너무 고생하셨습니다.👍🏻 몇 가지 생각해볼만한 것을 코멘트 드렸으니, 해당 프로젝트에 리팩토링은 어렵더라도 이후에 진행되는 두번째 토이프로젝트에 꼭 반영해보시는 것을 조언드립니다. 지금까지 너무 고생하셨습니다.🙇🏻♂️
cancelText="취소" | ||
> | ||
<Button type="primary" block> | ||
수정완료 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
개인적으로 "수정완료"라는 것의 의미는 수정이 이루어진 상태를 의미하기 때문에 버튼에 사용되는 것은 적절하지 않은 것으로 보입니다. 버튼을 누를 때, 잠깐 헷갈렸거든요. 수정하시겠습니까? 에 대한 물음의 답변으로 "확인"이 나을 것으로 보입니다.
수정완료 | |
확인 |
<label className="myinfo__input--label">아이디</label> | ||
<input | ||
className="myinfo__input--input" | ||
type="email" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
onChange={(e) => setPhoneNumber(e.target.value)} | ||
placeholder="-를 제외한 숫자만 입력해 주세요." | ||
disabled={ | ||
accountNumber.length === digits && isValidAccountNumber |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
계좌 연결시, 입력에 대한 유효성 안내문구 없이 다음 입력인 휴대폰 번호 입력이 비활성화가 되어서 사용할 때 헷갈리는 것이 있었어요. 앞에 계좌번호 입력이 유효하지 않은 경우, 에러 상태를 사용해서 "잘못된 계좌번호 입니다." 또는 "계좌번호의 길이가 깁니다."라는 안내문구를 보여주도록 해보면 좋을 것 같습니다.
@@ -0,0 +1,5 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prettier 룰을 사용하셨네요. 해당 룰만으로도 충분히 팀원 분들의 코드 스타일이 통일이 됐는지 궁금합니다.
<p className="NotFound-description"> | ||
죄송합니다, 페이지를 찾을 수 없습니다. | ||
</p> | ||
<Button className="NotFound-btn"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
클릭이벤트가 Link 컴포넌트에 걸리기 때문에 문구 영역외에는 클릭이 되지 않습니다. Link 컴포넌트 내에 Button 컴포넌트를 매달거나 Button 컴포넌트에 이벤트를 바인딩하는 방식으로 구현하는 것이 좋을 것 같습니다:)
const accessToken = cookies.accessToken; | ||
|
||
// interface TabsProps {} | ||
const items = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
반영 감사드립니다.🙇🏻♂️
· 예약 날짜 및 시간 : | ||
</p> | ||
<ConfigProvider locale={locale}> | ||
<RangePicker |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RangePicker
컴포넌트와 필요한 메서드를 묶어서 하나의 컴포넌트로 생성하는 것을 추천드립니다. ProductDetail
컴포넌트는 해당 상품의 예약을 표현해야하나, 날짜를 선택하는 로직을 분리해두면 훨씬 가독성이 좋아질 것 같아요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
프로젝트를 진행할 때 컴포넌트를 분리하는 기준을 정립하는 것이 아직 어려운 것 같습니다. 정답이 없어 다양한 방법을 볼 수 있는 것 같기도 하구요! 멘토님께서 추천해주신 이유를 '상품의 예약과 관련된 내용'을 보여주는 ProductDetail 컴포넌트이기 때문에, '상품의 예약 날짜'를 선택하는 로직은 다른 컴포넌트로 분리하여 가독성을 높일 수 있다는 것으로 이해했는데 맞을까요? 멘토님 코멘트를 참고하여 추후에 컴포넌트 분리를 적극적으로 시도해보겠습니다! 감사합니다:)
if (logInData.accessToken) { | ||
if (!cookies.accessToken) { | ||
const accessToken = logInData.accessToken; | ||
setCookies('accessToken', accessToken, { path: '/' }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
쿠키를 사용하여 로그인을 구현하신 것 칭찬드립니다. 실제로 브라우저 내의 저장장소를 개인적으로 정리해두시면 추후 기술면접에 도움이 될 거예요.
@@ -0,0 +1,59 @@ | |||
@import './common.scss'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SCSS를 사용하여 BEM 방법론을 잘 구현하신 것 같아요. SCSS와 BEM 방법론이 잘 어울리네요👍🏻 저도 SCSS를 써봐야겠습니다!
const productInfo = useCookies(['productInfo'])[0].productInfo; | ||
const productAddress = ['서울특별시 강남구 강남대로 364', '11층 11E 공간']; | ||
// 선택한 예약 날짜 및 시간에서 날짜만 반환 | ||
const reserveStartDate = cookieSavedDate.startTime.split('T')[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아래의 로직은 현재의 상태값을 사용하여 연산된 결과값을 사용하기 위해 정의되어 있습니다. cookieSavedDate
의 상태값이 변화하면 아래의 로직은 재호출되어 새로운 formattedStartDate
, formattedEndDate
를 연산하고, 해당 값을 컴포넌트 내에서 사용하는데요.
const reserveStartDate = cookieSavedDate.startTime.split('T')[0];
const reserveEndDate = cookieSavedDate.endTime.split('T')[0];
const formatStartDate = new Date(reserveStartDate);
const formatEndDate = new Date(reserveEndDate);
const startYear = formatStartDate.getFullYear();
const startMonth = formatStartDate.getMonth() + 1;
const startDay = formatStartDate.getDate();
const endYear = formatEndDate.getFullYear();
const endMonth = formatEndDate.getMonth() + 1;
const endDay = formatEndDate.getDate();
const formattedStartDate = `${startYear}년 ${startMonth}월 ${startDay}일`;
const formattedEndDate = `${endYear}년 ${endMonth}월 ${endDay}일`;
// 선택한 예약 입실 시간, 퇴실 시간 반환
const reserveStartTime = cookieSavedDate.startTime
.split('T')[1]
.split(':')[0];
const reserveEndTime = cookieSavedDate.endTime.split('T')[1].split(':')[0];
여기서 중요한 것은 이 로직은 컴포넌트 내에 선언되어있기 때문에 cookieSavedDate
의 상태값 뿐 만 아니라 전혀 무관한 값인 isModalOpen
과 같은 상태값이 바뀌어도 해당 로직이 재실행 됩니다. (컴포넌트가 리렌더링 되면 내부에 있는 로직이 전부 호출되기 때문!) 이러한 로직의 재호출을 피하기 위해 우리는 연산을 통해 얻어지는 값을 메모라이징(미리 연산된 값을 메모리에 저장해둔다.)하는 useMemo
를 사용합니다. 이를 통해 의존성 배열에 있는 상태값이 변하지 않으면 이 로직을 호출하지 않고 그대로 메모라이징된 값을 사용하도록 합니다.
const formattedDate = useMemo(() => {
const reserveStartDate = cookieSavedDate.startTime.split('T')[0];
const reserveEndDate = cookieSavedDate.endTime.split('T')[0];
const formatStartDate = new Date(reserveStartDate);
const formatEndDate = new Date(reserveEndDate);
const startYear = formatStartDate.getFullYear();
const startMonth = formatStartDate.getMonth() + 1;
const startDay = formatStartDate.getDate();
const endYear = formatEndDate.getFullYear();
const endMonth = formatEndDate.getMonth() + 1;
const endDay = formatEndDate.getDate();
const formattedStartDate = `${startYear}년 ${startMonth}월 ${startDay}일`;
const formattedEndDate = `${endYear}년 ${endMonth}월 ${endDay}일`;
// 선택한 예약 입실 시간, 퇴실 시간 반환
const reserveStartTime = cookieSavedDate.startTime
.split('T')[1]
.split(':')[0];
const reserveEndTime = cookieSavedDate.endTime.split('T')[1].split(':')[0];
return {
startDate: formattedStartDate,
endDate: formattedEndDate,
startTime: reserveStartTime,
endTime: reserveEndTime,
}
}, [cookieSavedDate]);
위의 로직을 useMemo
를 통해 메모라이징 하였습니다. cookieSavedDate
가 바뀌게 되면 자동적으로 formattedDate
의 값은 재계산되어서 우리가 원하는 값으로 변화할테고, 이외의 isModalOpen
등 다른 상태값이 바뀌어도 재연산이 발생하지 않기 때문에 성능적인 이점을 가질 수 있습니다.
조금 더 힙한 useMemo
를 사용하여 멋지게 코딩하세요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
멘토님 코멘트 덕분에 useMemo와 메모라이징에 대해 새롭게 알게 됐습니다! 추가적으로 학습하여 리팩토링 or 이후 프로젝트 적용에 꼭 참고하겠습니다. 감사합니다:)
📌 프로젝트 소개
OP-AL
📌 배포
OP-AL ← 클릭 시 이동 ❗
📌 프로젝트 기간
2023.5.30 ~ 2023.7.2
📌 Team
리덕스 설정
마이페이지
계좌, 구매내역
제품 검색 기능,
검색 리스트
마이페이지 내정보
결제페이지
📌 프로젝트 상세 프리뷰
메인
제품
마이페이지
인증
📌 기술스택
Development
Config
Environment
Deployment