-
Notifications
You must be signed in to change notification settings - Fork 4
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
글 작성/수정 폼 리팩토링해서 폼 훅 분리하기 #838
Conversation
- 수정 페이지 url로 접근 시 마감시간이 지난 글을 수정할 수 있는 오류 수정 - 타임피커 모달을 확인을 누르면 시간 검증없이 시간이 설정되는 오류 수정
- 폼데이터를 만드는 정보객체 재활용 - 마감시간 정보가 stringData 타입으로 수정되며 0일 0시간 0분을 검열하기 어려워짐 -> 코드 삭제
- 모달에 넣는 buttonInfo가 ButtonHTMLAttributes 상속하게 만들어 type을 지정할 수 있도록 함 - 모달과 폼에서 모두 사용되어 타입을 전역 타입폴더로 분리
⚡️ Lighthouse report!
|
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.
복잡했던 PostForm이 훨씬 읽기 좋아졌다고 생각해요 👍
그리고 저도 수아의 의견처럼 useContent와 useText를 모아서 반환하는 함수는 과하다고 생각이 들어요
const errorMessage = checkValidationPost(writingPostInfo); | ||
if (errorMessage) return addMessage(errorMessage); | ||
|
||
const formData = convertToFormdata(writingPostInfo); |
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.
const formData = convertToFormData(writingPostInfo);
카멜케이스로 변경 가능할까요?
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.
이 부분이 일부로 Formdata로 하신 부분이군요!
저는 FormData와 Formdata의 미묘한 차이를 잘 모르겠어요. 변수명 짓는것은 정말 어렵네요
convertToPostFormData 은 어떠세요?
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.
저도 이 함수가 글 작성 폼에 한정되어 있다고 생각해서 우스의 의견에 동의합니다!
}; | ||
|
||
const secondaryButton = { | ||
const secondaryButton: ButtonInfo = { |
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.
모달의 Button 관련 타입이 types로 나오게 된 이유가 궁금했는데 사용하는 곳에서 타입을 선언해줘야 했군요!
ButtonInfo도 좋지만 Modal 관련 버튼 타입이니까 ModalButton 은 어떠세요?
|
||
import { deleteOverlappingNewLine } from '@utils/deleteOverlappingNewLine'; | ||
|
||
export const convertToFormdata = ({ |
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.
유틸 함수로 분리되니 코드 가독성이 올라갔어요 😀
if (deadline && Number(new Date(deadline)) < Date.now()) { | ||
addMessage('마감완료된 게시물은 수정할 수 없습니다.'); | ||
return <Navigate to={PATH.HOME} />; | ||
} | ||
|
||
if (postId && writer && !checkWriter(writer.id)) { | ||
addMessage('사용자가 작성한 글만 수정할 수 있습니다.'); | ||
return <Navigate to={PATH.HOME} />; | ||
} | ||
|
||
if (serverVoteInfo && serverVoteInfo.allPeopleCount !== 0) { | ||
addMessage('투표한 사용자가 있어 글 수정이 불가합니다.'); | ||
return <Navigate to={PATH.HOME} />; | ||
} |
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.
예외 처리로 서비스 완성도가 올라갔네요 👍👍👍
fe-리뷰완 |
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.
if (deadline && Number(new Date(deadline)) < Date.now()) { | ||
addMessage('마감완료된 게시물은 수정할 수 없습니다.'); | ||
return <Navigate to={PATH.HOME} />; | ||
} | ||
|
||
if (postId && writer && !checkWriter(writer.id)) { | ||
addMessage('사용자가 작성한 글만 수정할 수 있습니다.'); | ||
return <Navigate to={PATH.HOME} />; | ||
} | ||
|
||
if (serverVoteInfo && serverVoteInfo.allPeopleCount !== 0) { | ||
addMessage('투표한 사용자가 있어 글 수정이 불가합니다.'); | ||
return <Navigate to={PATH.HOME} />; | ||
} |
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.
음 이 3가지 validation도 함수로 분리해보는거 어떨까요?
3가지 유효성 검사(수정 가능한지 아닌지 검사)를 통과하면 isValid 가 true가 되고,
if(!isPostFormEditValid) {
addMessage('유효하지 않은 이유');
return <Navigate to={PATH.HOME} />;
}
요런 식으로 리팩터링할 여지가 보이네요!!
resetDeadline, | ||
getFinalDeadline, | ||
getLimitDeadline, | ||
} = useDeadline(createTime, deadline); |
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.
👍👍👍
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.
궁금한 점! 혹시 파일명과 함수명을 다르게 하신 이유가 있나요??
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.
오 중간에 수정했는데 신경쓰지 못했습니다 수정하겠습니다!
if (serverVoteInfo && serverVoteInfo.allPeopleCount !== 0) { | ||
addMessage('투표한 사용자가 있어 글 수정이 불가합니다.'); | ||
return <Navigate to={PATH.HOME} />; | ||
} | ||
|
||
// 마감시간 관련 핸들러 | ||
const handleDeadlineButtonClick = (option: DeadlineOptionInfo) => { |
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.
이 함수 로직도 useDeadline hook에 포함시키는건 어떠신가요?
hook 하나 분리한 김에 관심사 같은 것은 최대한 하나로 빼내는 것도 좋을거 같아서요!
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.
저도 고민했는데, 핸들러 로직은 버튼이나 모달 등 다른 정보와 관련있는데 훅 안으로 옮기는 것이 관심사가 섞이는 것이라고 생각했습니다. 그래서 마감시간을 수정하는 로직만 훅으로 두고 핸들러에서 훅에서 return 함수/변수를 조작-이용하는 것이 좋다고 생각했습니다!
setSelectTimeOption(option.name); | ||
setUserSelectTime(targetTime); | ||
|
||
changeDeadlineOption(option); | ||
}; | ||
|
||
const handleResetButton = () => { |
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.
이 함수도 useDeadline hook에 포함시키는게 좋을거 같아요!
(handleResetDeadline 이라는 함수명으로)
const errorMessage = checkValidationPost(writingPostInfo); | ||
if (errorMessage) return addMessage(errorMessage); | ||
|
||
const formData = convertToFormdata(writingPostInfo); |
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.
저도 이 함수가 글 작성 폼에 한정되어 있다고 생각해서 우스의 의견에 동의합니다!
hour: userSelectTime.hour, | ||
day: userSelectTime.day, | ||
minute: userSelectTime.minute, | ||
hour: userSelectedDHMTime.hour, |
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.
👍👍구체적인 변수명으로 의미가 더 명확해졌네요!!
|
||
import { Option } from '@components/common/MultiSelect/types'; | ||
|
||
interface OptionWithIsServerId extends WritingVoteOptionType { |
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.
혹시 OptionWithIsServerId 에서 Is 는 어떤 의미인지 궁금합니다!
타입 확장 좋아요!!!👍
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.
여기서 isServerId는 클라이언트(프론트엔드)에서만 가지는 필드입니다
서버에서 준 선택지와 사용자가 입력한 선택지를 구분하기 위함으로 해당 필드가 포함된 옵션 타입이라고 명시하기 위함입니다.
@@ -217,7 +230,7 @@ export const WithTimePicker = () => { | |||
> | |||
<S.Body> | |||
<S.Description>최대 {MAX_DEADLINE}일을 넘을 수 없습니다.</S.Description> | |||
<TimePickerOptionList time={time} setTime={setTime} /> | |||
<TimePickerOptionList time={time} setTime={changeDeadlinePicker} /> |
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.
오 구체적인 상태가 되었네요!👍
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.
어떤 스토리인지 이름도 같이 구체화하면 좋을거 같아서, 혹시 WithTimePicker 라는 이름 대신 WithDeadlineTimePicker 로 바꿔주실 수 있나요?!
return ( | ||
<> | ||
<TimePickerOptionList time={time} setTime={setTime} /> | ||
<TimePickerOptionList time={time} setTime={changeDeadlinePicker} /> |
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.
함수명 바꾼 김에 Default 라는 스토리 이름 대신 Deadline 으로 바꿔주실 수 있나요?
fe-리뷰완 |
🔥 연관 이슈
close: #837
📝 작업 요약
⏰ 소요 시간
1일
🔎 작업 상세 설명
🌟 논의 사항
글 작성/수정 폼 리팩토링을 하면 많이 비워질 줄 알았는데, 생각보다 비워지지 않더라구요.
useText, useContentImage 등 훅을 사용하는 경우 이걸 다시 모아 리턴하는 것이 유의미할지 잘 모르겠어서 그대로 두었습니다. 분리를 하는 것도 의미가 있겠지만 파악하기 위한 뎁스가 깊어져 오히려 가독성을 떨어트릴 수 있다고 생각했습니다.
결과적으로 폼 안에는
위 로직들만 존재하고 있습니다. 혹시 더 뺄 수 있거나 리팩토링 가능해보인다면 말씀해주세요!
ps. 함수명 중 ---Formdata가 있는데, 이는 문법상 이상하지만 FormData라고 하면 오히려 폼데이터 형식처럼 와닿지 않을 것 같아서 붙여서 작성했습니다. 이에 대해 좋은 의견이 있다면 말씀해주세요!(변수명 너무 어렵네요😢)