-
Notifications
You must be signed in to change notification settings - Fork 0
[refactor] isPending을 이용한 연속 클릭 방지 추가 #157
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
The head ref may contain hidden characters: "156-refactor-\uC5F0\uC18D-\uD074\uB9AD-\uBC29\uC9C0-\uCD94\uAC00"
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,21 +15,21 @@ function ClubFeePage() { | |
| const { clubId } = useParams(); | ||
| const navigate = useNavigate(); | ||
| const { data: clubFee } = useGetClubFee(Number(clubId)); | ||
| const { applyToClub } = useApplyToClub(Number(clubId)); | ||
| const { applyToClub, isPending: isApplyingToClub } = useApplyToClub(Number(clubId)); | ||
| const { answers, clubId: storedClubId } = useClubApplicationStore(); | ||
|
|
||
| useEffect(() => { | ||
| if (storedClubId == null || storedClubId !== Number(clubId)) { | ||
| navigate(`/clubs/${clubId}/apply`, { replace: true }); | ||
| } | ||
| }, [storedClubId, clubId, navigate]); | ||
| const { mutateAsync: uploadImage } = useUploadImage('CLUB'); | ||
| const { mutateAsync: uploadImage, isPending: isUploadingImage } = useUploadImage('CLUB'); | ||
|
|
||
| const fileInputRef = useRef<HTMLInputElement>(null); | ||
| const [previewUrl, setPreviewUrl] = useState<string | null>(null); | ||
| const [imageFile, setImageFile] = useState<File | null>(null); | ||
| const [isSubmitting, setIsSubmitting] = useState(false); | ||
| const { value: isImageOpen, setTrue: openImage, setFalse: closeImage } = useBooleanState(); | ||
| const isSubmitting = isApplyingToClub || isUploadingImage; | ||
|
|
||
| useEffect(() => { | ||
| return () => { | ||
|
|
@@ -49,14 +49,8 @@ function ClubFeePage() { | |
|
|
||
| const handleSubmit = async () => { | ||
| if (!imageFile) return; | ||
| setIsSubmitting(true); | ||
|
|
||
| try { | ||
| const { fileUrl } = await uploadImage(imageFile); | ||
| await applyToClub({ answers, feePaymentImageUrl: fileUrl }); | ||
| } finally { | ||
| setIsSubmitting(false); | ||
| } | ||
| const { fileUrl } = await uploadImage(imageFile); | ||
| await applyToClub({ answers, feePaymentImageUrl: fileUrl }); | ||
| }; | ||
|
Comment on lines
50
to
54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major 페이지의 제출 비즈니스 로직은 커스텀 훅으로 분리해 주세요.
As per coding guidelines "비즈니스 로직은 커스텀 훅으로 분리되어 있는지". 🤖 Prompt for AI Agents중복 제출 방지를 위해 현재는 버튼 🔧 제안 수정 const handleSubmit = async () => {
- if (!imageFile) return;
+ if (!imageFile || isSubmitting) return;
const { fileUrl } = await uploadImage(imageFile);
await applyToClub({ answers, feePaymentImageUrl: fileUrl });
};🤖 Prompt for AI Agents |
||
|
|
||
| return ( | ||
|
|
@@ -129,7 +123,7 @@ function ClubFeePage() { | |
| onClick={handleSubmit} | ||
| disabled={!imageFile || isSubmitting} | ||
| > | ||
| 제출하기 | ||
| {isSubmitting ? '제출 중...' : '제출하기'} | ||
| </button> | ||
|
|
||
| {isImageOpen && previewUrl && ( | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,3 @@ | ||||||||||||||||||||||||||||||||||||||||||||
| import { useState } from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { useNavigate } from 'react-router-dom'; | ||||||||||||||||||||||||||||||||||||||||||||
| import type { ClubDetailResponse } from '@/apis/club/entity'; | ||||||||||||||||||||||||||||||||||||||||||||
| import HumanIcon from '@/assets/svg/human.svg'; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -14,20 +13,11 @@ interface ClubIntroProps { | |||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| function ClubIntro({ clubDetail }: ClubIntroProps) { | ||||||||||||||||||||||||||||||||||||||||||||
| const navigate = useNavigate(); | ||||||||||||||||||||||||||||||||||||||||||||
| const { createChatRoom } = useChat(); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const [isSubmitting, setIsSubmitting] = useState(false); | ||||||||||||||||||||||||||||||||||||||||||||
| const { createChatRoom, isCreatingChatRoom } = useChat(); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const handleInquireClick = async () => { | ||||||||||||||||||||||||||||||||||||||||||||
| if (isSubmitting) return; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||
| setIsSubmitting(true); | ||||||||||||||||||||||||||||||||||||||||||||
| const response = await createChatRoom(clubDetail.presidentUserId); | ||||||||||||||||||||||||||||||||||||||||||||
| navigate(`/chats/${response.chatRoomId}`); | ||||||||||||||||||||||||||||||||||||||||||||
| } finally { | ||||||||||||||||||||||||||||||||||||||||||||
| setIsSubmitting(false); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| const response = await createChatRoom(clubDetail.presidentUserId); | ||||||||||||||||||||||||||||||||||||||||||||
| navigate(`/chats/${response.chatRoomId}`); | ||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
18
to
21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 에러 처리 부재:
🛡️ 에러 처리 추가 제안 const handleInquireClick = async () => {
+ try {
const response = await createChatRoom(clubDetail.presidentUserId);
navigate(`/chats/${response.chatRoomId}`);
+ } catch {
+ // 에러 처리 (토스트 등)
+ }
};📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -70,11 +60,11 @@ function ClubIntro({ clubDetail }: ClubIntroProps) { | |||||||||||||||||||||||||||||||||||||||||||
| <button | ||||||||||||||||||||||||||||||||||||||||||||
| type="button" | ||||||||||||||||||||||||||||||||||||||||||||
| onClick={handleInquireClick} | ||||||||||||||||||||||||||||||||||||||||||||
| disabled={isSubmitting} | ||||||||||||||||||||||||||||||||||||||||||||
| disabled={isCreatingChatRoom} | ||||||||||||||||||||||||||||||||||||||||||||
| className="bg-primary text-body3 flex items-center justify-center gap-1 rounded-sm py-3 text-white" | ||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||
| <PaperPlaneIcon className="text-white" /> | ||||||||||||||||||||||||||||||||||||||||||||
| {isSubmitting ? '이동 중...' : '문의하기'} | ||||||||||||||||||||||||||||||||||||||||||||
| {isCreatingChatRoom ? '이동 중...' : '문의하기'} | ||||||||||||||||||||||||||||||||||||||||||||
| </button> | ||||||||||||||||||||||||||||||||||||||||||||
| </Card> | ||||||||||||||||||||||||||||||||||||||||||||
| </> | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
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.
🧩 Analysis chain
🏁 Script executed:
Repository: BCSDLab/KONECT_FRONT_END
Length of output: 3867
🏁 Script executed:
rg -n "createChatRoom" --type=ts --type=tsx -A 5 -B 2Repository: BCSDLab/KONECT_FRONT_END
Length of output: 95
🏁 Script executed:
fd "useChat" --type=ts --type=tsxRepository: BCSDLab/KONECT_FRONT_END
Length of output: 237
🏁 Script executed:
rg "createChatRoom" -A 5 -B 2Repository: BCSDLab/KONECT_FRONT_END
Length of output: 1994
🏁 Script executed:
rg "useChat" -lRepository: BCSDLab/KONECT_FRONT_END
Length of output: 419
에러 처리 및 캐시 무효화 누락 처리 필요
createChatRoomMutation에 에러 핸들링이 없을 뿐만 아니라, 성공 시 캐시 무효화도 누락되어 있습니다. ClubIntro.tsx의handleInquireClick에서도 try-catch가 없어 요청 실패 시 사용자 피드백이 전혀 없습니다.다른 mutation들(sendMessage, toggleMute)과 일관되게 다음을 추가하세요:
onSuccess에서 chatRoomList 캐시 무효화onError핸들러 또는 컴포넌트에서 에러 처리🤖 Prompt for AI Agents