Skip to content

Conversation

@cksrlcks
Copy link
Collaborator

@cksrlcks cksrlcks commented Jan 2, 2025

요구사항

기본

  • 스프린트 미션 1 ~ 7에 대해 typescript를 적용해주세요

심화

  • any타입을 최소한으로 써주세요

주요 변경사항

  • 1차 프로젝트를 하면서 배우게된 점들을 리팩토링했습니다.
  • react hook form, zod 도입
    • 로그인, 회원가입, 상품작성, 상품수정, 코멘트작성, 코멘트수정에 적용했습니다.
    • zod로 스키마를 변경했습니다.
  • 타입스크립트 작업을 했습니다.
    • 변환 작업후 사용하는 쪽에서 한번 더 타입이 제대로 노출되고 있는지 점검했습니다.
      스크린샷 2025-01-02 시간: 15 36 10

멘토에게

  • 배포 URL : https://sprint-mission-chanki-react.netlify.app/
  • 셀프 코드 리뷰를 통해 질문 이어가겠습니다.
  • 멘토링시간에 알려주신 spell check 이용해보니 오타가 많았습니다.ㅠ
  • zod와 react hook form으로 특수한 필드들을 처리하는게 어려웠습니다...
    • react hook form을 커스텀으로 hook을 만들어서 처리했습니다. (react hook form을 바로 사용하는데 부족한 값들이 있어서)
    • 커스텀훅에서 form 제출 에러상태를 관리하도록 했습니다.
  • react hook form을 쓰다보니 좀 궁금한점이 생겼습니다.
    • 자꾸 컴포넌트들이 특정 라이브러리의 인터페이스에 의존하게 되는것 같은데, 이렇게 수정을 진행도 맞는 방향일까요?
    • 리액트 훅폼에서 제공하는 폼상태, 필드상태, 에러등에 대한 인터페이스를 활용해서 컴포넌트를 수정해가고 있어서 든 의문점입니다.
    • 알려주신 방법을 보고 필드컴포넌트와 리액트훅폼의 controller를 연결하는 어뎁터 컴포넌트를 작성해서 수정했습니다. 감사합니다. ^^

- 통신에러와 필드에러값을 넘겨줄수있도록 변형
- 기본값 수정
- type 수정
- 리액트훅폼에 맞게 변경
- 리액트훅폼 적용
- 스키마 작성
@cksrlcks cksrlcks requested a review from withyj-codeit January 2, 2025 04:09
@cksrlcks cksrlcks added the 매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다. label Jan 2, 2025
Comment on lines +36 to +45
function handleSumbitWithError(submitFn: (data: T) => Promise<void>) {
return handleSubmit(async function (data) {
try {
setFormError(null);
await submitFn(data);
} catch (error) {
setFormError(error as Error);
}
});
}
Copy link
Collaborator Author

@cksrlcks cksrlcks Jan 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

react hook form에서는 폼제출의 에러상태는 따로 관리해야하는것 같아서 커스텀훅에 같이 포함시켰습니다.

Comment on lines 3 to 27
export type ListQueryParams = {
page: number;
pageSize: number;
keyword: string;
orderBy: string;
};

export type PaginationResponse<T> = {
totalCount: number;
list: T[];
};

export type BaseData = {
updatedAt: string;
createdAt: string;
id: number;
};

export type DefaultFieldState = {
error?: FieldError | undefined;
invalid: boolean;
isTouched: boolean;
isDirty: boolean;
isValidating: boolean;
};
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추후 재사용하거나, 공통적으로 쓰이는것 같은 타입들을 분리했는데,
최대한 직관적이게 이름을 지어보려고했는데, 아직 좀 부족한것 같습니다.

if (!error) {
return null;
}
export function Error({ error }: { error: string }) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

react hook form의 FieldError의 message를 전달받아서 랜더링하는 컴포넌트는
그냥 string을 받는다라고 더 넓은 의미로 작성을 해도되는걸까요?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵~ react hook form에 종속적이지 않게 Error ui에 필요하다고 생각하는 인터페이스로 만드시면 좋아요.

Copy link
Contributor

@withyj-codeit withyj-codeit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고 많으셨어요~👍

- useForm의 모드를 'onBlur'로 설정할때에는 필드에 전달된 props중 onBlur가 실행이 되어야 벨리데이션이 된다.
- 직접 값을 업데이트해줄때는 (특수한 필드의 경우), useForm의 반환값중 setValue를 이용하면 값 업데이트와 벨리데이션이 작동한다.
- react hook form에 컴포넌트를 연결할때에는 한겹의 어뎁터 레이어를 설정하여 컴포넌트 내부에서 react hook form의 의존성이 없도록 작성하는 방법을 사용하자.
- watch를 통해 각 필드에 value값을 전달하면 하나의 필드가 업데이트 될때마다 전체가 리랜더링이 되어버린다. (Controller, useController 등을 통해서 전달해야함)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

try {
await onCommentSubmit(data);
alert(message);
window.location.reload();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reload() 는 어떤 맥락에서 필요해요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코멘트 작성후에 데이터 갱신 및 폼초기화를 한번에 하려고 새로고침을 해버렸습니다.

기초프로젝트 이후에 다시 생각해보니 그냥 새로고침은 앱전체를 다시 리셋하는거라
선언적으로 state를 변화시켜서 앱ui상태를 업데이트하는방식으로 교체하겠습니다.

if (!error) {
return null;
}
export function Error({ error }: { error: string }) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵~ react hook form에 종속적이지 않게 Error ui에 필요하다고 생각하는 인터페이스로 만드시면 좋아요.

// 특정한 행동에 onChange를 활용해 값을 업데이트할때에는
// onBlur를 실행하지 못해서, onChange가 호출될때 함께 onBlur가 호출되도록 개선했습니다.
//
// (정상적으로 연결되는 컴포넌트에서도 한번더 벨리데이션을 호출한다고 해서 문제가 되지 않을것 같아서)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 정도 이슈일 경우 onBlur를 묶어주는 것도 좋다고 생각해요.
이후에 특정 커스텀 컴포넌트 지원을 위해 이슈 케이스가 다양해지면 하나의 FieldAdapter에서 전부 처리하기보다 특정 케이스에 맞는 Adapter로 분리하는 것도 좋을 것 같아요.

if (onClick) {
onClick();
}
onClick && onClick();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

간결함을 위한 변경인 것 같아서 onClick?.() 도 권해봅니다.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vite에 기본적으로 setting된 tsconfig에서는
onClick && onClick(); 이게 eslint 오류로 안잡혔는데

next프로젝트로 넘어와서는 이부분이
표현식의 결과값을 사용하지 않은 케이스라
no-unused-expressions rule에 위반이 된다고 해서
코멘트해주신방향으로 수정중에 있습니다 ㅠ

@withyj-codeit withyj-codeit merged commit 10e56ff into codeit-bootcamp-frontend:React-김찬기 Jan 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants