Skip to content
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

[강성구] Sprint10 #302

Merged

Conversation

L1m3Kun
Copy link
Collaborator

@L1m3Kun L1m3Kun commented Aug 16, 2024

요구사항

체크리스트

  • 상품 등록 페이지

  • 상품 등록 페이지 주소는 “/addboard” 입니다.

  • 게시판 이미지는 최대 한개 업로드가 가능합니다.

  • 각 input의 placeholder 값을 정확히 입력해주세요.

  • 이미지를 제외하고 input 에 모든 값을 입력하면 ‘등록' 버튼이 활성화 됩니다.

  • 회원가입, 로그인 api를 사용하여 받은accessToken을 사용하여 게시물 등록을 합니다.

  • ‘등록’ 버튼을 누르면 게시물 상세 페이지로 이동합니다.

  • 상품 상세 페이지

  • 상품 상세 페이지 주소는 “/board/{id}” 입니다.

  • 댓글 input 값을 입력하면 ‘등록' 버튼이 활성화 됩니다.

  • 활성화된 ‘등록' 버튼을 누르면 댓글이 등록됩니다

주요 변경사항

  • dayjs 추가
  • ts-pattern 추가
  • react-hook-form 추가
  • axios intercepter에 의한 refreshtoken 사용 기능 추가

멘토에게

  • 한글 이미지 업로드 시에, api string 길이 제한에 걸려 500 에러가 뜨던데 이런경우에는 어떤식으로 처리하면 좋은가요?

@L1m3Kun L1m3Kun requested a review from wlgns2223 August 16, 2024 14:50
@L1m3Kun L1m3Kun added 매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다. 미완성🫠 죄송합니다.. labels Aug 16, 2024
@L1m3Kun L1m3Kun removed the 미완성🫠 죄송합니다.. label Aug 17, 2024
Comment on lines +14 to +27
const { boardItemId } = context.query;
const boardData = await getBoardDetail({ boardItemId: `${boardItemId}` });
const boardComments = await getBoardComments({
articleId: `${boardItemId}`,
limit: 3,
});
console.log(boardComments);
return {
props: {
boardData,
boardComments,
},
};
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

클라이언트에서 넘어오는 boardItemId이 항상 존재한다는 보장이 없으므로 데이터가 없을 수도, 에러가 날 수도 있습니다. 그럴때를 대비해서 페이지에 따라서 디폴트값이나 null일때 에러처리를 해주면 좋겠네요 !

Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

안 그래도 관련 에러처리를 찾아보고 있었는데 찾아주셔서 감사합니다 ☺️

</Link>
<S.Categories>
<Link href={ROUTER_PATH.BOARD.default}>
<S.CategoryItem $isSelected={nowPath[1] === 'boards'}>
Copy link
Collaborator

Choose a reason for hiding this comment

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

$isSelected에서 $는 따로 의미가 있나요? 궁금해서 물어봅니다 ㅎㅎ

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

props 를 다룰 때, style 관련된 내용과 component함수 관련된 내용을 보기 편하게 하기 위해서 style 관련 내용에 $를 붙여 표시했습니다 😄

Comment on lines +14 to +27
const { boardItemId } = context.query;
const boardData = await getBoardDetail({ boardItemId: `${boardItemId}` });
const boardComments = await getBoardComments({
articleId: `${boardItemId}`,
limit: 3,
});
console.log(boardComments);
return {
props: {
boardData,
boardComments,
},
};
};
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 +30
export const useInputValue = () => {
const [inputValues, setInputValues] = useState<InputValues>(INITIAL_VALUES);

const handleInputValuesChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => {
const target = e.target;
const targetName = target.name;

if (targetName === 'image') {
const target = e.target as HTMLInputElement;
setInputValues((prev) => ({ ...prev, [targetName]: target.files![0] }));
} else {
setInputValues((prev) => ({ ...prev, [targetName]: target.value }));
}
};
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 +29 to +43
const boardApi = boardMutation({ title, content });
if (itemImage) {
imageMutation({
image: itemImage[0],
onSuccess: (data) => {
boardApi({ image: data.url });
},
onError: () => {
boardApi({});
},
});
} else {
boardApi({});
}
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

커링을 이용하셨네요 ! 참신한 접근법인것 같습니다.
imageMutationonError일때 이미지가 없는채로 게시글을 업로드하기보다
아예 게시글을 업로드하지 않고 유저에게 문제가 생겼다는 걸 알려주는 편이 더 좋은 것 같습니다
이미지가 있을때 imageMutation -> boardAPI 하나의 트랜잭션처럼 관리되는게 좋다는 생각입니다.

Comment on lines +7 to +22
export const usePreview = ({ value }: PreviewProps) => {
const [preview, setPreview] = useState<string>('');

useEffect(() => {
if (!value || value.length < 1) return;
const nextPreview = URL.createObjectURL(value[0]);
setPreview(nextPreview);

return () => {
setPreview('');
URL.revokeObjectURL(nextPreview);
};
}, [value]);

return { preview };
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

preview 로직만 딱 분리해서 응집성이 있네요 !

Comment on lines +46 to +53
const PreviewContent = match(previewType)
.with({ type: 'empty' }, () => (
<S.EmptyPreview $size={size}></S.EmptyPreview>
))
.with({ type: 'file' }, () => (
<Preview preview={preview} size={size} onDelete={onDelete} />
))
.exhaustive();
Copy link
Collaborator

Choose a reason for hiding this comment

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

ts-pattern 사용 잘 하셨네용 !

content: e.boardComment,
})
.then((res) => {
router.reload();
Copy link
Collaborator

Choose a reason for hiding this comment

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

submit 후 최신 코멘트 리스트를 받아올때 reload보다는 리스트를 새로 받아오는 api를 호출하는게 더 낫습니다.
화면 리로드는 Next에서 상태관리를 많이 하고 있는 경우에 꽤 비용이 많이 드는 작업이라고 생각합니다 !

Comment on lines +7 to +13
const accessToken = process.env.NEXT_PUBLIC_ACCESS_TOKEN;
return await instance
.post<Article>(API_PATH.article, JSON.stringify(data), {
headers: {
Authorization: `Bearer ${accessToken}`,
},
})
Copy link
Collaborator

Choose a reason for hiding this comment

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

axios interceptor를 활용해서 토큰을 주입하면 어떨까요 !?

@wlgns2223 wlgns2223 merged commit 26ba91e into codeit-bootcamp-frontend:Next-강성구 Aug 20, 2024
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