-
Notifications
You must be signed in to change notification settings - Fork 23
[박수환] sprint11 #144
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
base: next-박수환
Are you sure you want to change the base?
[박수환] sprint11 #144
The head ref may contain hidden characters: "next-\uBC15\uC218\uD658"
Conversation
kimjong95
left a comment
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.
typescript를 제대로 활용하고싶다면, typescript에서 타입이 어떻게 추론되는지, 또한 어떠한 방식으로 타입을 지정할수있는지 학습이 필요할 것 같습니다.
typescript를 사용하지만 type시스템을 잘 활용하지 못한다면 오히려 javascript로만 작성할때보다 오버헤드가 발생할 것이고 불편하다고 느낄거에요.
| productId: string; | ||
| } | ||
|
|
||
| interface Comment { |
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.
model 혹은 viewModel의 형태를 가지고있는 타입 또는 interface는 별도의 파일로분리해서 export하고 원하는 사용처에서 가져가서 사용하면 좋을것 같아요. 아래에서 추가로 볼게요
| isError, | ||
| } = useQuery<Comment[], Error>({ | ||
| queryKey: ["product-comments", productId], | ||
| queryFn: () => axiosProductComments(productId), |
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.
현재 여기서 받는 response의 타입은 any일것 같습니다
| }; | ||
|
|
||
| //특정 상품의 댓글 가져오기 | ||
| export const axiosProductComments = async (productId: string) => { |
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.
때문에 여기서 받는 Response의 타입이 Promise<Response> 형태의 타입이여야 하고, 여기서 Comment타입이 사용되어야합니다.
현재는 컴포넌트레벨에서 타입을 정의해주고있는데, 타입추론 관점에서본다면 타입이 시작되는 시점에 타입을 적용해주셔야 해당 값 또는 함수를 사용하는 모든 하위의 코드들에서 타입이 추론될 수 있습니다.
타입스크립트에서는 타입추론을 통해서 모든 곳에 타입을 지정하지 않아도 되는 이유이기도 하고요. 이관점에서본다면 타입을 어디에 지정해주어야할지, 어디서 사용해야할지에 대한 고민이 필요합니다. 이코드를 살짝 수정한다면 다음과같이 수정할 수 있을것 같아요
export type Comment = {
id: string;
content: string;
user: { nickname: string };
createdAt: string;
}
export const axiosProductComments = async (productId: string): Promise<Comment[]> => {
const response = await axiosInstance.get<Comment[]>(`/productComment/${productId}`);
return response.data;
};그렇다면 이 함수의 값을 를 사용하는 곳에서는 모두 타입이 추론되겟죠?!
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.
그리고 필요하다면 Comment타입을 원하는곳에서 사용할수 있을거에요
| const [page, setPage] = useState(1); | ||
| const [pageSize, setPageSize] = useState(4); | ||
| const [selectedSort, setSelectedSort] = useState("좋아요순"); | ||
| const [searchQuery, setSearchQuery] = useState(""); |
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.
필요하다면 이곳에도 state들의 타입을 generic을통해서 지정해주면 좋고, 정렬값또한 타입을두고 사용한다면 더 가독성이 좋을것 같아요. 예를 들어볼게요
const SORT_OPTIONS = {
LIKE: "좋아요순",
LATEST: "최신순",
} as const;
// 타입 정의
type SortOptionKey = keyof typeof SORT_OPTIONS;
type SortOptionValue = (typeof SORT_OPTIONS)[SortOptionKey];
type SortApiValue = "like" | "latest";
// 정렬 옵션과 API 값 매핑 객체
const SORT_API_MAP: Record<SortOptionValue, SortApiValue> = {
[SORT_OPTIONS.LIKE]: "like",
[SORT_OPTIONS.LATEST]: "latest",
} as const;
...
const [selectedSort, setSelectedSort] = useState<SortOptionValue>(SORT_OPTIONS.LIKE);
...
const {
data: { products = [], total = 0 } = {},
isLoading,
error,
} = useQuery({
queryKey: ["products", searchQuery, selectedSort, page, pageSize],
queryFn: () =>
axiosProduct(
searchQuery,
SORT_API_MAP[selectedSort],
page,
pageSize
),
});예시에서는 조금 오버한 경향이 있지만, 사용하시는것처럼 key-value형태의 값과 타입이 필요하고 그 관리포인트가 늘어갈때 유용한 방법이기도 합니다.
| 상품 태그 | ||
| </div> | ||
| <div className="flex flex-wrap gap-2 mt-2"> | ||
| {product?.tags?.map((tag, index) => ( |
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.
- 위에서 product의 타입이 optional이 아니기때문에 해당 코드에서도 optional이 필요없을것 같아요.
- 마찬가지로 tags도 optional이 아니기때문에 필요없을것 같고요.
하지만 의도하지않게 product나 tags가 null이나 undefined형태로 들어올 수 있다면 이 컴포넌트의 상위에서 처리가 필요할수도 있을것 같아요.
위에 설명드린것 처럼 타입의 추론은 코드의선언부부터 사용측으로 추론이되기때문에 선언할때 부터 잘못사용하고있는지 확인이 필요합니다.
| selectedValue, | ||
| placeholder, | ||
| onValueChange, | ||
| className = "", |
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.
DropdownProps의 각 프로퍼티가 optional이고 이에대한 기본값을 지정해주기위해서 처리해주신것 같은데 좋습니다!
요구사항
기본
프론트엔드
멘토에게