Skip to content

Conversation

@dkslel1225
Copy link
Collaborator

@dkslel1225 dkslel1225 commented May 11, 2025

요구사항

배포 링크

https://react-15-7.netlify.app/

기본

상품 상세

  • 상품 상세 페이지 주소는 "/items/{productId}" 입니다.
  • response 로 받은 아래의 데이터로 화면을 구현합니다.
  • => favoriteCount : 하트 개수
  • => images : 상품 이미지
  • => tags : 상품태그
  • => name : 상품 이름
  • => description : 상품 설명
  • 목록으로 돌아가기 버튼을 클릭하면 중고마켓 페이지 주소인 "/items" 으로 이동합니다

상품 문의 댓글

  • 문의하기에 내용을 입력하면 등록 버튼의 색상은 "3692FF"로 변합니다.
  • response 로 받은 아래의 데이터로 화면을 구현합니다
  • => image : 작성자 이미지
  • => nickname : 작성자 닉네임
  • => content : 작성자가 남긴 문구
  • => description : 상품 설명
  • => updatedAt : 문의글 마지막 업데이트 시간

심화

  • []모든 버튼에 자유롭게 Hover효과를 적용하세요.

스크린샷

데스크탑

image

태블릿

image

모바일

image

등록 버튼 활성화, 코멘트 수정/삭제 폼

image

멘토에게

  • 셀프 코드 리뷰를 통해 질문 이어가겠습니다.

@dkslel1225 dkslel1225 requested a review from GANGYIKIM May 11, 2025 14:40
@dkslel1225 dkslel1225 self-assigned this May 11, 2025
@dkslel1225 dkslel1225 added the 순한맛🐑 마음이 많이 여립니다.. label May 11, 2025
Copy link
Collaborator

@GANGYIKIM GANGYIKIM left a comment

Choose a reason for hiding this comment

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

지윤님 7번째 미션 수고하셨습니다!
지금 배포사이트에서 확인해보니 페이지에서 새로고침시 에러가 나고 있어요!
React는 SPA 방식이기 때문에 접근 주소에 해당하는 페이지가 없기 때문에 위와 같은 현상이 발생합니다. netfliy 문서를 확인해서 수정해보세요~
다음 미션도 화이팅입니다!

Comment on lines +121 to +126
<button
className={styles["back-button"]}
onClick={() => navigate("/items")}
>
목록으로 돌아가기
</button>
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안
지금 코드만으로 보면 버튼 태그보다 Link 태그를 쓰는게 더 적절해보여요.
단순 페이지 이동이 아니라 특정 로직을 실행해야한다면 지금처럼 버튼 태그를 사용하셔도 좋지만 아니라면 Link 태그로 변경해주세요~
링크 태그를 사용하시면 마우스 오른쪽 클릭이나 새탭 기능도 제공이 가능해서 UX 측면에서도 좋습니다.

<textarea
className={styles["question__textarea"]}
id="comment"
value={message}
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안
지금처럼 textarea 값을 useState로 제어하면 사용자가 입력할 때마다 컴포넌트가 리렌더링됩니다.
지금 코드상에서는 textarea 값을 바꿔주는 것이 아니라 제어 컴포넌트로 관리할 필요가 없을 것 같아요!
이를 비제어 컴포넌트로 바꾸셔서 불필요한 리렌더링을 줄이시는 것을 추천드려요!

Comment on lines +108 to +114
<button
className={`${styles["submit-button-none"]} ${
message.trim() ? styles.active : ""
}`}
>
등록
</button>
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안
문의하기가 message 가 없을때 비활성화가 될 수 있게 해주세요~
또한 동적 class 를 활용하시기보다 css 가상클래스 :disabled를 통해 구현하시는 것이 더 적절할 것 같습니다.

Suggested change
<button
className={`${styles["submit-button-none"]} ${
message.trim() ? styles.active : ""
}`}
>
등록
</button>
<button
disabled={!!message.trim()}
className={`${styles["submit-button-none"]}`}
>
등록
</button>

</div>
</section>
<section className={styles["question"]}>
<form onSubmit={() => handleSubmit}>
Copy link
Collaborator

Choose a reason for hiding this comment

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

❗️ 수정요청

Suggested change
<form onSubmit={() => handleSubmit}>
<form onSubmit={handleSubmit}>

const [year, month, day] = createdAt.split("T")[0].split("-");
const formattedDate = `${year}. ${month}. ${day}`;

async function handleSubmit(e) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

💬 여담
코멘트 등록까지 구조를 잡아두신 점 좋아요~
다만 로그인후 사용가능한 기능이라 추후 완성하시면 될 것 같습니다!

import getComments from "../../API/getComments";
import { useNavigate } from "react-router";

export default function Product() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안
제 생각에는 아래처럼 비슷한 부분들을 모아두시는 것이 가독성 측면에서 더 좋을 것 같아요~

export default function Product() {
  const [product, setProduct] = useState();
  const [message, setMessage] = useState("");
  const navigate = useNavigate();
  const { productId } = useParams();

  async function handleSubmit(e) { ... }

  useEffect(() => { ...}, []);

  if (!product) return <div>로딩 중...</div>;
  return (...)
}


return (
<div className={styles.item}>
<div className={styles.item} onClick={onClick}>
Copy link
Collaborator

Choose a reason for hiding this comment

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

❗️ 수정요청
해당 컴포넌트 클릭시 해당 요소의 상세 페이지로 이동이니 Link 태그가 적절할 것 같아요!

Comment on lines +59 to +78
return (
<>
{isEmpty ? (
<div className={styles.isEmpty}>
<img src={empty} alt="comment empty" />
<p>아직 문의가 없어요</p>
</div>
) : (
<div className={styles["comment-content"]}>
{comments.map((comment) => (
<Comment
comment={comment}
handleModify={handleModify}
handleDelete={handleDelete}
/>
))}
</div>
)}
</>
);
Copy link
Collaborator

Choose a reason for hiding this comment

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

💊 제안
이런 경우 React fragment로 감싸지 않으시고 조건부 렌더링을 바로 하시면 됩니다~

Suggested change
return (
<>
{isEmpty ? (
<div className={styles.isEmpty}>
<img src={empty} alt="comment empty" />
<p>아직 문의가 없어요</p>
</div>
) : (
<div className={styles["comment-content"]}>
{comments.map((comment) => (
<Comment
comment={comment}
handleModify={handleModify}
handleDelete={handleDelete}
/>
))}
</div>
)}
</>
);
return { isEmpty ? (
<div className={styles.isEmpty}>
<img src={empty} alt="comment empty" />
<p>아직 문의가 없어요</p>
</div>
) : (
<div className={styles["comment-content"]}>
{comments.map((comment) => (
<Comment
comment={comment}
handleModify={handleModify}
handleDelete={handleDelete}
/>
))}
</div>
)};

useEffect(() => {
async function fetchComments() {
try {
const comments = await getComments(productIdNum, 3, 0);
Copy link
Collaborator

Choose a reason for hiding this comment

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

❗️ 수정요청
지금은 고정값으로 코멘트를 불러오고 있어요~
모든 코멘트가 보이도록 무한스크롤 방식으로 구현해주시면 좋겠습니다!

import { useState } from "react";
export default function Comment({ comment, handleModify, handleDelete }) {
const { content, updatedAt, id, writer } = comment;
const [show, setShow] = useState(false);
Copy link
Collaborator

Choose a reason for hiding this comment

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

💬 여담
reducer 를 사용해 아래처럼 간단하게도 작성 가능합니다~

Suggested change
const [show, setShow] = useState(false);
const [isShow, toggleIsShow] = useReducer((prev) => !prev, false);

@GANGYIKIM GANGYIKIM merged commit da8ce15 into codeit-bootcamp-frontend:React-전지윤 May 16, 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