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

feat(@yourssu/react): create usePreventDuplicateClick #55

Merged
merged 2 commits into from
Nov 6, 2024

Conversation

owl1753
Copy link
Collaborator

@owl1753 owl1753 commented Jul 6, 2024

1️⃣ 어떤 작업을 했나요? (Summary)

기존 코드에 영향을 미치지 않는 변경사항

  • usePreventDuplicateClick 훅 추가
  • usePreventDuplicateClick.test 테스트 추가
  • @testing-library/jest-dom devDendency 추가
  • docs 추가

2️⃣ 알아두시면 좋아요!

훅의 테스트를 위해 테스트 코드에서 더미 버튼을 만든 후 버튼의 disabled 속성 값에 disabled를 대입해서 이를 테스트 했습니다. 또한 100ms의 호출 시간을 가지는 콜백 함수를 mocking해서, 중복 실행 여부를 확인하였습니다.

3️⃣ 추후 작업

  • logging-system에 usePreventDuplicateClick 훅 적용
  • soomsil에 usePreventDuplicateClick 훅 적용

4️⃣ 체크리스트 (Checklist)

  • main 브랜치의 최신 코드를 pull 받았나요?

@owl1753 owl1753 added feat New feature or request react @yourssu/react labels Jul 6, 2024
@Hanna922
Copy link
Member

Hanna922 commented Jul 8, 2024

수고하셨어용! 제가 현재 노트북이 없는 관계로,, 리뷰는 11일 이후에 하도록 하겠숩니다😭

Copy link

@fecapark fecapark left a comment

Choose a reason for hiding this comment

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

👍
참고로 p4) 요거는 Pn 룰 입니다

Comment on lines +3 to +20
export const usePreventDuplicateClick = () => {
const [disabled, setDisabled] = useState(false);
const loadingRef = useRef(false);

const handleClick = useCallback(async (callback: () => Promise<void>) => {
if (loadingRef.current) return;

loadingRef.current = true;
setDisabled(true);

await callback();

loadingRef.current = false;
setDisabled(false);
}, []);

return { disabled, handleClick };
};

Choose a reason for hiding this comment

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

p4) 유틸리티의 관점에서는 usePreventDuplicateClick 보다는 usePromise 가 더 낫지 않나 싶네요.

Suggested change
export const usePreventDuplicateClick = () => {
const [disabled, setDisabled] = useState(false);
const loadingRef = useRef(false);
const handleClick = useCallback(async (callback: () => Promise<void>) => {
if (loadingRef.current) return;
loadingRef.current = true;
setDisabled(true);
await callback();
loadingRef.current = false;
setDisabled(false);
}, []);
return { disabled, handleClick };
};
export const usePromise = () => {
const [isPending, setIsPending] = useState(false);
const callPromise = useCallback(async (callback: () => Promise<void>) => {
setIsPending(true);
await callback();
setIsPending(false);
}, []);
return { isPending, callPromise };
};

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

지금 와서 생각난거지만 tanstack-query의 useMutation훅을 이용하면 pending 상태를 감지할 수 있으니까 굳이 이 훅이 필요할까 싶네요.

Comment on lines +8 to +10
if (loadingRef.current) return;

loadingRef.current = true;
Copy link

@fecapark fecapark Oct 27, 2024

Choose a reason for hiding this comment

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

p3) 굳이 ref를 사용할 필요가 없어보여요.
본래 목적이 이벤트 핸들러로 국한된다면 내부에서 상태와 세터를 같이 사용해도 문제 없을거예요.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

https://happysisyphe.tistory.com/72

위 글에 따르면 react에서는 state를 batch 단위로 비동기 적으로 업데이트하기 때문에, state만 가지고 중복 요청을 엄격하게 막는 것은 힘들다고 합니다.

따라서 ref는 실질적으로 중복 호출을 막도록 하는 역할이고, state는 button의 disabled 등에 대입해 리렌더링을 수행하도록 하는 역할이라고 생각하심 될 것 같습니다.

Choose a reason for hiding this comment

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

구두로 완료됐어요

@owl1753 owl1753 merged commit 7ce4ba7 into main Nov 6, 2024
1 check passed
@owl1753 owl1753 deleted the feat/use-prevent-duplicate-click branch November 6, 2024 07:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat New feature or request react @yourssu/react
Projects
None yet
Development

Successfully merging this pull request may close these issues.

feat: create usePreventDuplicate hook
3 participants