Skip to content

Commit

Permalink
feat(react): useBlockDoubleClick 추가 (#82)
Browse files Browse the repository at this point in the history
* feat(react): useBlockDoubleClick 추가

* imp: useBlockPromiseMultipleClick 훅 테스트코드 및 네이밍 수정 완료

* fix: 누락된 useBlockPromiseMultipleClick의 메서드 네이밍 변경 완료
  • Loading branch information
Sangminnn authored Apr 30, 2024
1 parent 483d648 commit 941af5d
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/react/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ export * from './useUnMount';
export * from './useVisibilityChange';
export * from './useWindowScrollTo';
export * from './useWindowSize';
export * from './useBlockPromiseMultipleClick';
25 changes: 25 additions & 0 deletions packages/react/src/hooks/useBlockPromiseMultipleClick/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useRef, useState } from 'react';

export const useBlockMultipleClick = () => {
const [isLoading, setIsLoading] = useState(false);
const isClicked = useRef(false);

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

isClicked.current = true;
setIsLoading(true);

await callback();

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

return {
isLoading,
blockMultipleClick,
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { describe, expect, it } from 'vitest';
import { screen, renderHook } from '@testing-library/react';
import { renderSetup } from '../../utils/test/renderSetup';
import { useBlockMultipleClick } from '.';

const delay = (time: number) => {
return new Promise<void>((resolve) => {
setTimeout(() => resolve(), time);
});
};

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

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

describe('useBlockMultipleClick', () => {
it('should block double click', async () => {
const mockFn = vi.fn(async () => await delay(1000));
const { result } = renderHook(useBlockMultipleClick);

const { blockMultipleClick } = result.current;
expect(result.current.isLoading).toBe(false);

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

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

const button = screen.getByRole('button');

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

expect(result.current.isLoading).toBe(true);
expect(mockFn).toHaveBeenCalledTimes(1);

await vi.advanceTimersByTimeAsync(1000);

expect(result.current.isLoading).toBe(false);
});
});

0 comments on commit 941af5d

Please sign in to comment.