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(react): useBlockPromiseMultipleClick 추가 #82

Merged
merged 3 commits into from
Apr 30, 2024

Conversation

Sangminnn
Copy link
Collaborator

@Sangminnn Sangminnn commented Apr 29, 2024

Overview

useDebounce는 동일한 이벤트가 중복으로 발생할 경우 이를 적게 호출할 수 있도록 도와줍니다. 또한 이러한 특징을 활용하여 순간적인 중복호출을 방지하는 역할을 하기도 하는데, 이는 시간을 다루는 작업이기에 완벽하게 막아낼 수 없습니다.

이 훅은 특정 Promise동작을 수행하는 동안은 중복호출이 불가능하도록 만들어둔 훅입니다.

양식에 맞지않거나 의견주실 부분이 있다면 편하게 말씀해주시면 감사드리겠습니다 :)

PR Checklist

  • All tests pass.
  • All type checks pass.
  • I have read the Contributing Guide document.
    Contributing Guide

Copy link

changeset-bot bot commented Apr 29, 2024

⚠️ No Changeset found

Latest commit: c40c98d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor

@ssi02014 ssi02014 left a comment

Choose a reason for hiding this comment

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

@Sangminnn 우선 기여를 위해 PR을 생성해주셔서 감사드립니다! 너무나도 유용한 훅인 것 같습니다...! ☺️
개인적으로 아래와 같은 추가 의견이 있는데 검토해주시면 감사드립니다!


beforeEach(() => {
  vi.useFakeTimers();
});

afterEach(() => {
  vi.useRealTimers();
});

describe('useBlockDoubleClick', () => {
  it('should block double click', async () => {
    const mockFn = vi.fn(async () => await delay(1000)); // (*) mock 함수를 활용
    const { result } = renderHook(useBlockDoubleClick);

    const { blockDoubleClick } = result.current;
    expect(result.current.isLoading).toBe(false); // (*) 아래 isLoading을 체크해주는 부분과 같이 통일해주는 것도 좋아보입니다!

    const onClick = () => blockDoubleClick(mockFn);

    const { user } = renderSetup(
      <button onClick={onClick}>TestButton</button>,
      { delay: null } // timeout issue 해결
    );

    const button = screen.getByRole('button'); // (*) getByRole 사용

    await user.click(button);
    await user.click(button);

    expect(result.current.isLoading).toBe(true);
    expect(mockFn).toBeCalledTimes(1);
    
    await vi.advanceTimersByTimeAsync(1000); // timer 추가

    expect(result.current.isLoading).toBe(false);  // (*) isLoading false 변경 케이스 추가
  });
});
  • 위와 같이 isLoading이 false로 변경되는 케이스도 추가하는 것은 어떨까요..!? 🤔

  • 추가적으로 blockDoubleClick으로 넘겨주는 함수가 몇 번 호출되었는지가 테스트 주요 포인트이기 때문에vi.fn을 활용해서 mockFn(목업 함수)를 생성하고 toBeCalledTimes와 함께 활용하면 좋을 것 같습니다!

    • counter와 같은 변수도 불 필요해 질 것 같습니다 🙇‍♂️
  • testing library/react 를 v15로 올렸다가 userEvent와 fakeTimer 사용 시에 timeout 이슈가 발생해서 아래 PR을 통해 다시 v14로 버전을 낮췄습니다.
    revert: @testing-library/react 버전 v15 -> v14 revert #83


const { user } = renderSetup(<button onClick={onClick}>TestButton</button>);

const button = screen.getByText('TestButton');
Copy link
Contributor

@ssi02014 ssi02014 Apr 29, 2024

Choose a reason for hiding this comment

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

Suggested change
const button = screen.getByText('TestButton');
const button = screen.getByRole('button');

getByRole로 요소를 가져오는게 더 좋아보이는데 어떨까요!? 아래 testing-library 문서를 통해 우선순위를 가이드하는데 getByRole의 우선순위가 높기 때문입니다! 🙏

https://testing-library.com/docs/queries/about/#priority

Comment on lines 3 to 27
const useBlockDoubleClick = () => {
const [isLoading, setIsLoading] = useState(false);
const isClicked = useRef(false);

const blockDoubleClick = async (callback: () => Promise<unknown>) => {
if (isClicked.current) {
return;
}

isClicked.current = true;
setIsLoading(true);

await callback();

isClicked.current = false;
setIsLoading(false);
};

return {
isLoading,
blockDoubleClick,
};
};

export default useBlockDoubleClick;
Copy link
Contributor

@ssi02014 ssi02014 Apr 29, 2024

Choose a reason for hiding this comment

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

export const useBlockDoubleClick = () => {}

default exports와 named exports를 혼합해서 사용하는 것을 권장하지 않기때문에 다른 모듈들과 컨벤션을 지키기 위해 useBlockDoubleClick을 default export말고 named export로 변경해주시면 감사드립니다!

@ssi02014
Copy link
Contributor

@Sangminnn 네이밍에 대한 고민도 있는데요! 사실 해당 훅은 더블 클릭 뿐만 아니라 3번, 4번그 이상도 막아주는 것으로 이해했는데요! 또한 Promise를 block하는 것이기 떄문에 usePromiseBlockMultipleClick 네이밍은 어떨까요!?

@Sangminnn
Copy link
Collaborator Author

@ssi02014 좋은 의견 감사합니다! 전반적으로 말씀주신 의견과 가이드를 반영하였고, hook의 네이밍만 use(동사)(명사) 의 형태로 작성하는 것이 더 자연스러워보여 이와 같이 네이밍을 변경해두었습니다!

@ssi02014
Copy link
Contributor

@Sangminnn 수정 감사합니다!! 앗 마지막으로 훅 내부 blockDoubleClick 함수도 네이밍을 수정이 되면 좋을 것 같습니다!!

@Sangminnn
Copy link
Collaborator Author

@ssi02014 감사합니다! 수정과정에서 해당 메서드의 네이밍 변경을 놓쳤네요! 맥락에 맞게 blockMultipleClick으로 메서드명을 수정해두었습니다 :)

Copy link

codecov bot commented Apr 30, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 82.44%. Comparing base (483d648) to head (c40c98d).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #82      +/-   ##
==========================================
+ Coverage   82.05%   82.44%   +0.39%     
==========================================
  Files          63       64       +1     
  Lines         535      547      +12     
  Branches      114      115       +1     
==========================================
+ Hits          439      451      +12     
  Misses         84       84              
  Partials       12       12              
Components Coverage Δ
@modern-kit/react 71.82% <100.00%> (+1.08%) ⬆️
@modern-kit/utils 97.76% <ø> (ø)

Copy link
Contributor

@ssi02014 ssi02014 left a comment

Choose a reason for hiding this comment

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

기여감사합니다🤗🤗🤗

@ssi02014 ssi02014 merged commit 941af5d into modern-agile-team:main Apr 30, 2024
3 checks passed
Sangminnn added a commit to Sangminnn/modern-kit that referenced this pull request Apr 30, 2024
@ssi02014 ssi02014 changed the title feat(react): useBlockDoubleClick 추가 feat(react): useBlockPromiseMultipleClick 추가 Apr 30, 2024
@ssi02014
Copy link
Contributor

ssi02014 commented Apr 30, 2024

@Sangminnn

@modern-kit/react@1.3.0이 release 🚀 되었습니다 !
아래 링크에서 해당 hook에 대한 추가된 문서를 확인하실 수 있습니다! 다시 한번 기여에 감사드립니다! 👍
useBlockPromiseMultipleClick

@Sangminnn Sangminnn deleted the feat/useBlockDoubleClick branch April 30, 2024 15:55
@ssi02014 ssi02014 added feature 새로운 기능 추가 @modern-kit/react @modern-kit/react labels May 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature 새로운 기능 추가 @modern-kit/react @modern-kit/react
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants