React 이정윤 스프린트미션 5#56
Hidden character warning
Conversation
…-김진영 Basic 김진영 스프린트 미션 1&2 제출
…int-mission-3 Basic 이보희 스프린트 미션 3 제출
pers0n4
left a comment
There was a problem hiding this comment.
현재 React로 작성된 코드 구조가 html 파일처럼 작성되어 있는데, 아무래도 기존에 작성된 html 파일을 React로 전환하는 과정을 거치다 보니 그럴 수도 있을 것 같다는 생각이 듭니다.
React의 철학과 구조상 React를 잘 사용하기 위해서는 컴포넌트를 최대한 잘게 나누는 게 좋습니다. 극단적으로는 스타일이 적용되는 html element마다 하나의 컴포넌트로 정의할 수도 있습니다. 거의 모든 UI 라이브러리에서 html의 div, a, span 등을 Box나 Link, Text로 추상화하듯이 말이죠.
모든 기본 element를 React 컴포넌트로 바꾸는 것이 강제 되어야 하는 건 아니지만, 통으로 작성된 마크업은 적절한 단위로 나누어 보면 좋을 것 같습니다.
There was a problem hiding this comment.
같은 경로에 있는데 어떤 파일은 camelCase로, 어떤 파일은 PascalCase로 작성되어 있네요. 프로젝트 내 모든 파일이 같은 네이밍 케이스로 통일되어야 할 필요는 없지만, 최소한 같은 맥락상에 존재하는 파일들은 혼란을 줄이기 위해서 네이밍 케이스를 맞춰주는 게 좋습니다.
There was a problem hiding this comment.
main과 비슷해 보이는데 이 파일은 정체가 무엇인가요? 잘못 추가된 파일이라면 정리해주세요.
| const params = new URLSearchParams(); | ||
| params.set("page", String(page)); | ||
| params.set("pageSize", String(pageSize)); | ||
| if (orderBy) params.set("orderBy", orderBy); | ||
| if (keyword) params.set("keyword", keyword); | ||
|
|
||
| const res = await fetch(`${BASE_URL}?${params.toString()}`); |
There was a problem hiding this comment.
params는 URLSearchParams로 잘 처리하셨네요. url도 URL 인스턴스로 생성하면 search params를 포함해서 같이 처리할 수도 있답니다.
There was a problem hiding this comment.
커스텀 훅을 정의해두고 한 번도 사용하지 않은 건 조금 아쉽네요.
아무래도 useProducts 훅 자체가 재사용하기에 용이하지 않는 구조다 보니 그럴 수도 있을 것 같다 싶네요.
useProducts에서 처리하는 getProducts api를 직접 호출하는 페이지에서 실제로 어떻게 로직을 구성하셨는지 다시 파악해보고 useProducts 훅을 사용하기 좋은 구조로 바꿔보시면 좋을 것 같습니다.
|
|
||
| export function useProducts({ page, sort, query, pageSize }) { | ||
| const [products, setProducts] = useState([]); | ||
| const [totalCount, setTotalCount] = useState(0); |
There was a problem hiding this comment.
count 같은 값은 state로 정의하지 않아도 됩니다.
products.length로도 쉽게 알아낼 수 있고, api에서 반환되는 데이터를 함수 내부 지역 변수로 받아서 바로 반환할 수도 있습니다.
| const maxPageButtons = 5; | ||
| let startPage = Math.max(1, currentPage - Math.floor(maxPageButtons / 2)); | ||
| let endPage = Math.min(totalPages, startPage + maxPageButtons - 1); | ||
|
|
||
| if (endPage - startPage + 1 < maxPageButtons) { | ||
| startPage = Math.max(1, endPage - maxPageButtons + 1); | ||
| } | ||
|
|
||
| const pageNumbers = []; | ||
| for (let i = startPage; i <= endPage; i++) { | ||
| pageNumbers.push(i); | ||
| } |
There was a problem hiding this comment.
컴포넌트 내부에 명령형 코드가 많이 작성되는 경향은 코드를 읽기 어렵기 만들기 때문에 지양하는 게 좋습니다.
- 한두 줄로 끝나는 간단한 코드라면 선언형으로 작성하거나 e.g. Array.from(...)
- 조금 더 길거나 복잡한 로직이 들어가는 코드라면 책임 분리를 위해 커스텀 훅으로 구현하는 게 좋습니다.
요구사항
기본 요구사항
공통
[x] Github에 스프린트 미션 PR을 만들어 주세요.
[x] React를 사용해 진행합니다.
중고마켓 페이지
[x] PC, Tablet, Mobile 디자인에 해당하는 중고마켓 페이지를 만들어 주세요.
[x] 중고마켓 페이지 url path는 별도로 설정하지 않고, '/'에 보이도록 합니다.
[x] 상단 네비게이션 바, 푸터는 랜딩 페이지와 동일한 스타일과 규칙으로 만들어주세요.
[x] 상품 데이터는 https://panda-market-api.vercel.app/docs/에 명세된 GET 메소드 "/products" 를 활용해주세요.
[x] 상품 목록 페이지네이션 기능을 구현합니다.
[x] 드롭 다운으로 "최신 순" 또는 "좋아요 순"을 선택해서 정렬을 구현하세요.
[x] 상품 목록 검색 기능을 구현합니다.
[x] 베스트 상품 데이터는 https://panda-market-api.vercel.app/docs/에 명세된 GET 메소드 "/products"의 정렬 기준 favorite을 사용해주세요.
심화 요구사항
공통
[x] 커스텀 hook을 만들어 필요한 곳에 활용해 보세요.
중고마켓 페이지
[x] 중고 마켓의 카드 컴포넌트 반응형 기준은 다음과 같습니다.
베스트 상품
Desktop : 4열
Tablet : 2열
Mobile : 1열
전체 상품
Desktop : 5열
Tablet : 3열
Mobile : 2열
반응형에 따른 페이지 네이션 기능을 구현합니다.
반응형으로 보여지는 물품들의 개수를 다르게 설정할때 서버에 보내는 pageSize값을 적절하게 설정합니다.
주요 변경사항
스크린샷
멘토에게