Skip to content

Commit

Permalink
Merge pull request #30 from mbti-nf-team/feat/nft-team-react-hook
Browse files Browse the repository at this point in the history
  • Loading branch information
saseungmin authored Jul 28, 2023
2 parents daf17c5 + 37edff5 commit d191bf9
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/silver-years-exercise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nft-team/react": minor
---

feat(@nft-team/react): useLessThenScrollY, useThrottleCallback hook 적용
2 changes: 2 additions & 0 deletions packages/react/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@ export { default as useBoolean } from './useBoolean';
export { default as useDebounce } from './useDebounce';
export { default as useIsMounted } from './useIsMounted';
export { default as useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';
export { default as useLessThenScrollY } from './useLessThenScrollY';
export { default as useResizeViewportHeight } from './useResizeViewportHeight';
export { default as useThrottleCallback } from './useThrottleCallback';
export { default as useTimeout } from './useTimeout';
45 changes: 45 additions & 0 deletions packages/react/src/hooks/useLessThenScrollY.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { act, fireEvent, renderHook } from '@testing-library/react';

import useLessThenScrollY from './useLessThenScrollY';

describe('useLessThenScrollY', () => {
beforeEach(() => {
jest.useFakeTimers();
});

afterEach(() => {
jest.clearAllTimers();
});

const useLessThenScrollYHook = () => renderHook(() => useLessThenScrollY(given.scrollY));

context('스크롤 위치가 기준값보다 작거나 같은 경우', () => {
const scrollY = 50;

given('scrollY', () => scrollY);

it('true를 반환해야만 한다', async () => {
const { result } = useLessThenScrollYHook();

act(() => {
fireEvent.scroll(window, { target: { scrollY } });
jest.advanceTimersByTime(200);
});

expect(result.current).toBeTruthy();
});
});

context('스크롤 위치가 기준값보다 큰 경우', () => {
it('false를 반환해야만 한다', async () => {
const { result } = useLessThenScrollYHook();

act(() => {
fireEvent.scroll(window, { target: { scrollY: 200 } });
jest.advanceTimersByTime(200);
});

expect(result.current).toBeFalsy();
});
});
});
24 changes: 24 additions & 0 deletions packages/react/src/hooks/useLessThenScrollY.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useCallback, useEffect, useState } from 'react';

import useThrottleCallback from './useThrottleCallback';

function useLessThenScrollY(targetScrollY = 0, delay = 200): boolean {
const [isLessThenScrollY, setIsLessThenScrollY] = useState<boolean>(true);

const handleScrollAction = useCallback(
() => setIsLessThenScrollY(window.scrollY <= targetScrollY),
[targetScrollY],
);

const throttledCallback = useThrottleCallback(handleScrollAction, delay);

useEffect(() => {
window.addEventListener('scroll', throttledCallback);

return () => window.removeEventListener('scroll', throttledCallback);
}, [throttledCallback]);

return isLessThenScrollY;
}

export default useLessThenScrollY;
45 changes: 45 additions & 0 deletions packages/react/src/hooks/useThrottleCallback.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { act, renderHook } from '@testing-library/react';

import useThrottleCallback from './useThrottleCallback';

describe('useThrottleCallback', () => {
const delay = 200;
const callback = jest.fn();

beforeEach(() => {
jest.clearAllMocks();
jest.useFakeTimers();
});

afterEach(() => {
jest.clearAllTimers();
});

const useThrottleCallbackHook = () => renderHook(() => useThrottleCallback(callback, delay));

context('delay 시간이 되지 않은 경우', () => {
it('callback 함수가 호출되지 않아야만 한다', async () => {
const { result } = useThrottleCallbackHook();

act(() => {
result.current();
jest.advanceTimersByTime(100);
});

expect(callback).not.toHaveBeenCalled();
});
});

context('delay 시간이 된 경우', () => {
it('callback 함수가 호출되어야만 한다', async () => {
const { result } = useThrottleCallbackHook();

act(() => {
result.current();
jest.advanceTimersByTime(delay);
});

expect(callback).toHaveBeenCalled();
});
});
});
21 changes: 21 additions & 0 deletions packages/react/src/hooks/useThrottleCallback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useCallback, useRef } from 'react';

function useThrottleCallback<U extends never[]>(
callback: (...args: U) => void,
delay: number,
) {
const timer = useRef<ReturnType<typeof setTimeout> | null>(null);

const throttledCallback = useCallback((...args: U) => {
if (!timer.current) {
timer.current = setTimeout(() => {
callback(...args);
timer.current = null;
}, delay);
}
}, [callback, delay]);

return throttledCallback;
}

export default useThrottleCallback;

0 comments on commit d191bf9

Please sign in to comment.