Skip to content

Conversation

@hhjin1
Copy link
Collaborator

@hhjin1 hhjin1 commented Feb 22, 2025

요구사항

기본

  • 상품 등록 페이지 주소는 "/additem" 입니다.
  • [] 페이지 주소가 “/additem” 일때 상단네비게이션바의 '중고마켓' 버튼의 색상은 “3692FF”입니다.
  • 상품 이미지는 최대 한개 업로드가 가능합니다.
  • 각 input의 placeholder 값을 정확히 입력해주세요.
  • 이미지를 제외하고 input에 모든 값을 입력하면 '등록' 버튼이 활성화 됩니다.

심화

  • 이미지 안의 X 버튼을 누르면 이미지가 삭제됩니다.
  • 추가된 태그 안의 X 버튼을 누르면 해당 태그는 삭제됩니다.

주요 변경사항

  • git ignore에 env파일 추가
  • API 요청 시 axios 사용
  • 반응형을 위한 환경변수 추가
  • jsx파일 내 styled-components를 별도 styles 파일로 분리�
  • 파일구조 변경

스크린샷

image

멘토에게

  • mission5 브렌치에서 mission6 작업을 진행하여 reset soft를 사용해서 새로운 mission6 브렌치에 하나의 커밋으로 푸쉬하였습니다 😓
  • 셀프 코드 리뷰를 통해 질문 이어가겠습니다.

@hhjin1 hhjin1 requested a review from kiJu2 February 22, 2025 01:58
@hhjin1 hhjin1 self-assigned this Feb 22, 2025
@hhjin1 hhjin1 added the 매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다. label Feb 22, 2025
@kiJu2
Copy link
Collaborator

kiJu2 commented Feb 25, 2025

스프리트 미션 하시느라 수고 많으셨어요.
학습에 도움 되실 수 있게 꼼꼼히 리뷰 하도록 해보겠습니다. 😊

@kiJu2
Copy link
Collaborator

kiJu2 commented Feb 25, 2025

mission5 브렌치에서 mission6 작업을 진행하여 reset soft를 사용해서 새로운 mission6 브렌치에 하나의 커밋으로 푸쉬하였습니다 😓

넵넵 ! 😊 참고하겠습니다 !

Comment on lines +25 to +26
#환경변수 무시
.env
Copy link
Collaborator

Choose a reason for hiding this comment

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

크으 ~ 굿굿 👍

환경변수를 만들고 gitignore에 추가하셨군요 ! 😊
피드백 반영 넘 좋습니당

Comment on lines +7 to +10
try {
const response = await axios.get(`${BASE_URL}/products`, {
params: { page, pageSize, orderBy, keyword },
});
Copy link
Collaborator

Choose a reason for hiding this comment

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

axios를 적용해보셨군요 ! 👍

ㅠㅠㅠ 피드백 수용을 넘 잘하세요 👍 좋은 경험이 될거라 생각해요.

다만, 하나 더 제안드리고 싶은건 instance를 생성하고 적용해볼 수 있어요:

어떻게 세팅하면 될까? 🤔

instance를 만들어서 export를 하고 사용해보는 것 정도로 시도해보면 좋을 것 같아요. axios-instance 파일을 만들어서 instance를 생성하고 export한 후 사용해보는건 어떨까요?
다음과 같이 만들어볼 수 있어요:

const baseURL = process.env.NEXT_PUBLIC_LINKBRARY_BaseURL;

const instance = axios.create({
  baseURL: baseURL,
  headers: {
    'Content-Type': 'application/json',
  },
});

export default instance

axios instance

인가에 필요한 accessTokenlocalStorage가 있다면 axios의 인터셉터를 활용할 수 있습니다 !

인터셉터는 혼자 해결해보시는 것을 권장드립니다. 혹시 모르시겠으면 다음 위클리 미션에 질문해주세요. 😊

사용 방법 🚀

사용 방법은 정말 간단해요. 다음과 같이 사용할 수 있습니다:

instance.get(`/user/${userId}`)

딱 보니. 마이그레이션도 정말 쉽게 할 수 있겠죠? 😊

axios API

queryParams.append("keyword", keyword);
return response.data;
} catch (error) {
throw new Error(`HTTP error: ${error.response?.status || error.message}`);
Copy link
Collaborator

Choose a reason for hiding this comment

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

(제안) error.message를 먼저 반환시키는건 어떨까요?

Suggested change
throw new Error(`HTTP error: ${error.response?.status || error.message}`);
throw new Error(`HTTP error: ${error.response?.message || error.status}`);

message에 서버로부터의 에러가 포함되어있을 수 있을 것 같아요.
만약 서버 에러 메시지가 포함되어있다면 유저에게 노출할 수도 있겠구요 !
상태만 반환하게 된다면 어떤 에러인지 유저, 그리고 컴포넌트에서도 파악하기 어려울 수 있겠죠?:

example: 400 상태만 가지고는 이메일 형식 불일치인지, 빈 값인지 알 수 없을거예요.

Comment on lines +7 to +32
export default function ImageUploader() {
const [previewImage, setPreviewimage] = useState(null);
const [showLimitText, setShowLimitText] = useState(false);

const handleImageChange = (e) => {
const file = e.target.files[0];
if (file) {
const imageUrl = URL.createObjectURL(file);
setPreviewimage(imageUrl);
setShowLimitText(false); // 새로 업로드 성공했으니 문구 지우기
}
};

const handleRemoveImage = () => {
setPreviewimage(null);
setShowLimitText(false); // 이미지 삭제했으니 문구 지우기
};

const handleUploadClick = (e) => {
if (previewImage) {
e.preventDefault();
setShowLimitText(true); // 문구 보여주기
}
};

const isImageUploaded = !!previewImage;
Copy link
Collaborator

Choose a reason for hiding this comment

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

굿굿 ! 컴포넌트가 참 깔끔한데요? 💯

Comment on lines +15 to +16
const updatedTags = [...tags, inputValue.trim()];
setTags(updatedTags);
Copy link
Collaborator

Choose a reason for hiding this comment

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

굿굿 ! 배열을 새로 만들어서 상태를 변경하셨군요 ! 👍

배열의 경우 요소를 추가/삭제 하는 것이 아닌 새로운 주소의 배열로 변경을 해줘야하지요. 훌륭합니다 😊

setTags(updatedTags);
onChange(updatedTags);
}
setTimeout(() => setInputValue(""), 0); // 입력 후 초기화 + 엔터 눌렀을 때 새로고침 방지 비동기처리
Copy link
Collaborator

Choose a reason for hiding this comment

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

setTimeout를 없애도 되지 않을까요? 🤔

Suggested change
setTimeout(() => setInputValue(""), 0); // 입력 후 초기화 + 엔터 눌렀을 때 새로고침 방지 비동기처리
setInputValue("")

Comment on lines +12 to +27
const maxItems =
window.innerWidth <= BREAKPOINTS.MOBILE
? size === "large "
? 1
: 4
: window.innerWidth <= BREAKPOINTS.TABLET
? size === "large"
? 2
: 6
: window.innerWidth <= BREAKPOINTS.LAPTOP
? size === "large"
? 3
: 8
: size === "large"
? 4
: 10;
Copy link
Collaborator

@kiJu2 kiJu2 Feb 25, 2025

Choose a reason for hiding this comment

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

삼항 연산자가 많아지면 가독성이 떨어질 수 있지욤.

다음과 같이 정의하고 사용해볼 수 있을 것 같아요 !:

    const breakpoints = [
      { maxWidth: BREAKPOINTS.MOBILE, values: { large: 1, default: 4 } },
      { maxWidth: BREAKPOINTS.TABLET, values: { large: 2, default: 6 } },
      { maxWidth: BREAKPOINTS.LAPTOP, values: { large: 3, default: 8 } },
    ];

위와 같이 정의해두고 필요한 값을 찾아볼 수 있어요:

    const matchedBreakpoint =
      breakpoints.find((bp) => window.innerWidth <= bp.maxWidth) || {
        values: { large: 4, default: 10 },
      };

    const maxItems = matchedBreakpoint.values[size === "large" ? "large" : "default"];

마찬가지로 if가 많아지거나 조건이 많이 붙는다면 객체 혹은 배열로 정의하고 find나 키로 접근하여 가독성 및 유지보수성을 좋게 만들어볼 수 있습니다 ! 😊

@kiJu2
Copy link
Collaborator

kiJu2 commented Feb 25, 2025

수고하셨습니다 혜진님 !
갑자기 너무 열심히 하시는데요? ㅎㅎㅎ 금방 성장하시는게 느껴져요 !
setTimeout은 의도적으로 넣으신 것 같아요. 제가 히스토리를 잘 이해하지 못하는 거일 수도 있으니 혹시 질문 있으시면 DM 주세욤 😊

이번에도 정말 수고 많으셨습니다 혜진님 ! 👍👍

@kiJu2 kiJu2 merged commit 4589c8d into codeit-bootcamp-frontend:React-황혜진 Feb 25, 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