From 1a524113be467980cf1307d0eeb3f18ffada0cb4 Mon Sep 17 00:00:00 2001 From: Jiwoo So <58384366+jiwooproity@users.noreply.github.com> Date: Tue, 13 Aug 2024 14:20:33 +0900 Subject: [PATCH 1/5] Feature: add useThrottle hook --- README.md | 1 + packages/usehooks-ts/README.md | 1 + packages/usehooks-ts/src/index.ts | 1 + packages/usehooks-ts/src/useThrottle/index.ts | 1 + .../src/useThrottle/useThrottle.demo.tsx | 24 +++++++ .../src/useThrottle/useThrottle.md | 5 ++ .../src/useThrottle/useThrottle.test.ts | 62 +++++++++++++++++++ .../src/useThrottle/useThrottle.ts | 33 ++++++++++ 8 files changed, 128 insertions(+) create mode 100644 packages/usehooks-ts/src/useThrottle/index.ts create mode 100644 packages/usehooks-ts/src/useThrottle/useThrottle.demo.tsx create mode 100644 packages/usehooks-ts/src/useThrottle/useThrottle.md create mode 100644 packages/usehooks-ts/src/useThrottle/useThrottle.test.ts create mode 100644 packages/usehooks-ts/src/useThrottle/useThrottle.ts diff --git a/README.md b/README.md index 48dc0486..8fc28562 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,7 @@ function Component() { - [`useSessionStorage`](https://usehooks-ts.com/react-hook/use-session-storage) — uses the [sessionStorage API](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) to persist state across page reloads. - [`useStep`](https://usehooks-ts.com/react-hook/use-step) — manages and navigates between steps in a multi-step process. - [`useTernaryDarkMode`](https://usehooks-ts.com/react-hook/use-ternary-dark-mode) — manages ternary (system, dark, light) dark mode with local storage support. +- [`useThrottle`](https://usehooks-ts.com/react-hook/use-throttle) — provides a stottle function. - [`useTimeout`](https://usehooks-ts.com/react-hook/use-timeout) — handles timeouts in React components using the [setTimeout API](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout). - [`useToggle`](https://usehooks-ts.com/react-hook/use-toggle) — manages a boolean toggle state in React components. - [`useUnmount`](https://usehooks-ts.com/react-hook/use-unmount) — runs a cleanup function when the component is unmounted. diff --git a/packages/usehooks-ts/README.md b/packages/usehooks-ts/README.md index 48dc0486..8fc28562 100644 --- a/packages/usehooks-ts/README.md +++ b/packages/usehooks-ts/README.md @@ -84,6 +84,7 @@ function Component() { - [`useSessionStorage`](https://usehooks-ts.com/react-hook/use-session-storage) — uses the [sessionStorage API](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) to persist state across page reloads. - [`useStep`](https://usehooks-ts.com/react-hook/use-step) — manages and navigates between steps in a multi-step process. - [`useTernaryDarkMode`](https://usehooks-ts.com/react-hook/use-ternary-dark-mode) — manages ternary (system, dark, light) dark mode with local storage support. +- [`useThrottle`](https://usehooks-ts.com/react-hook/use-throttle) — provides a stottle function. - [`useTimeout`](https://usehooks-ts.com/react-hook/use-timeout) — handles timeouts in React components using the [setTimeout API](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout). - [`useToggle`](https://usehooks-ts.com/react-hook/use-toggle) — manages a boolean toggle state in React components. - [`useUnmount`](https://usehooks-ts.com/react-hook/use-unmount) — runs a cleanup function when the component is unmounted. diff --git a/packages/usehooks-ts/src/index.ts b/packages/usehooks-ts/src/index.ts index 9577bd16..531d1a58 100644 --- a/packages/usehooks-ts/src/index.ts +++ b/packages/usehooks-ts/src/index.ts @@ -27,6 +27,7 @@ export * from './useScrollLock' export * from './useSessionStorage' export * from './useStep' export * from './useTernaryDarkMode' +export * from './useThrottle' export * from './useTimeout' export * from './useToggle' export * from './useUnmount' diff --git a/packages/usehooks-ts/src/useThrottle/index.ts b/packages/usehooks-ts/src/useThrottle/index.ts new file mode 100644 index 00000000..e15e51af --- /dev/null +++ b/packages/usehooks-ts/src/useThrottle/index.ts @@ -0,0 +1 @@ +export * from './useThrottle' diff --git a/packages/usehooks-ts/src/useThrottle/useThrottle.demo.tsx b/packages/usehooks-ts/src/useThrottle/useThrottle.demo.tsx new file mode 100644 index 00000000..03d8b665 --- /dev/null +++ b/packages/usehooks-ts/src/useThrottle/useThrottle.demo.tsx @@ -0,0 +1,24 @@ +import { useState } from 'react' + +import { useEventListener } from 'src/useEventListener' + +import { useThrottle } from './useThrottle' + +export default function Component() { + const [state, setState] = useState(0) + const throttle = useThrottle() + + const onScroll = () => { + throttle(() => { + setState(state => state + 1) + }, 1000) + } + + useEventListener('scroll', onScroll) + + return ( +
+ {state} +
+ ) +} diff --git a/packages/usehooks-ts/src/useThrottle/useThrottle.md b/packages/usehooks-ts/src/useThrottle/useThrottle.md new file mode 100644 index 00000000..22f53e39 --- /dev/null +++ b/packages/usehooks-ts/src/useThrottle/useThrottle.md @@ -0,0 +1,5 @@ +Use the throttle function with one simple function + +Related hooks: + +- [`useThrottle()`](/react-hook/use-throttle) diff --git a/packages/usehooks-ts/src/useThrottle/useThrottle.test.ts b/packages/usehooks-ts/src/useThrottle/useThrottle.test.ts new file mode 100644 index 00000000..adedec79 --- /dev/null +++ b/packages/usehooks-ts/src/useThrottle/useThrottle.test.ts @@ -0,0 +1,62 @@ +import { useState } from 'react' + +import { act, renderHook } from '@testing-library/react' + +import { useThrottle } from './useThrottle' + +describe('use throttle()', () => { + it('shoud use thorttle be ok', () => { + const { result } = renderHook(() => useThrottle()) + const throttle = result.current + + expect(typeof throttle).toBe('function') + }) + + it('shoud default value works', () => { + const countRender = renderHook(() => useState(0)) + const [count, setCount] = countRender.result.current + + const throttleRender = renderHook(() => useThrottle()) + const throttle = throttleRender.result.current + + act(() => { + throttle(() => { + setCount(state => state + 1) + }) + + throttle(() => { + setCount(state => state + 1) + }) + + setTimeout(() => { + expect(count).toBe(1) + }, 1000) + }) + }) + + it('shoud interval param works', () => { + const countRender = renderHook(() => useState(0)) + const [count, setCount] = countRender.result.current + + const throttleRender = renderHook(() => useThrottle()) + const throttle = throttleRender.result.current + + act(() => { + throttle(() => { + setCount(state => state + 1) + }, 1) + + throttle(() => { + setCount(state => state + 1) + }, 1) + + throttle(() => { + setCount(state => state + 1) + }, 2) + + setTimeout(() => { + expect(count).toBe(2) + }, 1000) + }) + }) +}) diff --git a/packages/usehooks-ts/src/useThrottle/useThrottle.ts b/packages/usehooks-ts/src/useThrottle/useThrottle.ts new file mode 100644 index 00000000..f7804e35 --- /dev/null +++ b/packages/usehooks-ts/src/useThrottle/useThrottle.ts @@ -0,0 +1,33 @@ +import { useRef } from 'react' + +/** + * Custom hook that provides a stottle function. + * @param {number} [defaultInterval] - The initial value for the throttle interval. + * @returns {(callback: () => void, interval?: number) => void} An executable throttle function + * a function to executed after a certain period of time based on the last function among the functions that are executed quickly. + * @public + * @see [Documentation](https://usehooks-ts.com/react-hook/use-throttle) + * @example + * ```tsx + * const throttle = useThrottle(2000); // Initial value is 2s + * // OR + * const throttle = useThrottle(); // Initial value is default value (1s) + * // Use throttle function in your component, Only one of the events that are processed redundantly can be processed. + * ``` + */ + +export function useThrottle( + defaultInterval = 1000, +): (callback: () => void, interval?: number) => void { + const ref = useRef() + + const throttle = (callback: () => void, interval?: number) => { + if (ref.current !== undefined) { + clearTimeout(ref.current) + } + + ref.current = setTimeout(callback, interval ?? defaultInterval) + } + + return throttle +} From 25f1c9714bfb500fa0c91e8a277b792b29a08c5a Mon Sep 17 00:00:00 2001 From: Jiwoo So <58384366+jiwooproity@users.noreply.github.com> Date: Wed, 14 Aug 2024 18:31:13 +0900 Subject: [PATCH 2/5] Fix: Edited useRef generic type Fix: - changed to > --- packages/usehooks-ts/src/useThrottle/useThrottle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/usehooks-ts/src/useThrottle/useThrottle.ts b/packages/usehooks-ts/src/useThrottle/useThrottle.ts index f7804e35..2e8ba8a1 100644 --- a/packages/usehooks-ts/src/useThrottle/useThrottle.ts +++ b/packages/usehooks-ts/src/useThrottle/useThrottle.ts @@ -19,7 +19,7 @@ import { useRef } from 'react' export function useThrottle( defaultInterval = 1000, ): (callback: () => void, interval?: number) => void { - const ref = useRef() + const ref = useRef>() const throttle = (callback: () => void, interval?: number) => { if (ref.current !== undefined) { From 36f04011586b81e2e576170d6dab8b898147a7de Mon Sep 17 00:00:00 2001 From: Jiwoo So <58384366+jiwooproity@users.noreply.github.com> Date: Thu, 15 Aug 2024 15:37:07 +0900 Subject: [PATCH 3/5] Fix: Change the throttle description --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8fc28562..d182d082 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ function Component() { - [`useSessionStorage`](https://usehooks-ts.com/react-hook/use-session-storage) — uses the [sessionStorage API](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) to persist state across page reloads. - [`useStep`](https://usehooks-ts.com/react-hook/use-step) — manages and navigates between steps in a multi-step process. - [`useTernaryDarkMode`](https://usehooks-ts.com/react-hook/use-ternary-dark-mode) — manages ternary (system, dark, light) dark mode with local storage support. -- [`useThrottle`](https://usehooks-ts.com/react-hook/use-throttle) — provides a stottle function. +- [`useThrottle`](https://usehooks-ts.com/react-hook/use-throttle) — A custom hooks that support throttle - [`useTimeout`](https://usehooks-ts.com/react-hook/use-timeout) — handles timeouts in React components using the [setTimeout API](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout). - [`useToggle`](https://usehooks-ts.com/react-hook/use-toggle) — manages a boolean toggle state in React components. - [`useUnmount`](https://usehooks-ts.com/react-hook/use-unmount) — runs a cleanup function when the component is unmounted. From 2747a4e3b297ce9e19ed49019e69d5eb45404faa Mon Sep 17 00:00:00 2001 From: Jiwoo So <58384366+jiwooproity@users.noreply.github.com> Date: Thu, 15 Aug 2024 15:38:29 +0900 Subject: [PATCH 4/5] Fix: Change the throttle description in packages README.md --- packages/usehooks-ts/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/usehooks-ts/README.md b/packages/usehooks-ts/README.md index 8fc28562..4c425f5f 100644 --- a/packages/usehooks-ts/README.md +++ b/packages/usehooks-ts/README.md @@ -84,7 +84,7 @@ function Component() { - [`useSessionStorage`](https://usehooks-ts.com/react-hook/use-session-storage) — uses the [sessionStorage API](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) to persist state across page reloads. - [`useStep`](https://usehooks-ts.com/react-hook/use-step) — manages and navigates between steps in a multi-step process. - [`useTernaryDarkMode`](https://usehooks-ts.com/react-hook/use-ternary-dark-mode) — manages ternary (system, dark, light) dark mode with local storage support. -- [`useThrottle`](https://usehooks-ts.com/react-hook/use-throttle) — provides a stottle function. +- [`useThrottle`](https://usehooks-ts.com/react-hook/use-throttle) — A custom hook that support throttle. - [`useTimeout`](https://usehooks-ts.com/react-hook/use-timeout) — handles timeouts in React components using the [setTimeout API](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout). - [`useToggle`](https://usehooks-ts.com/react-hook/use-toggle) — manages a boolean toggle state in React components. - [`useUnmount`](https://usehooks-ts.com/react-hook/use-unmount) — runs a cleanup function when the component is unmounted. From 3dd41002e1839d00f931d376946cabce48a020e9 Mon Sep 17 00:00:00 2001 From: Jiwoo So <58384366+jiwooproity@users.noreply.github.com> Date: Thu, 15 Aug 2024 15:39:20 +0900 Subject: [PATCH 5/5] Fix: Fix the throttle custom hook description --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d182d082..7ba2665a 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ function Component() { - [`useSessionStorage`](https://usehooks-ts.com/react-hook/use-session-storage) — uses the [sessionStorage API](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) to persist state across page reloads. - [`useStep`](https://usehooks-ts.com/react-hook/use-step) — manages and navigates between steps in a multi-step process. - [`useTernaryDarkMode`](https://usehooks-ts.com/react-hook/use-ternary-dark-mode) — manages ternary (system, dark, light) dark mode with local storage support. -- [`useThrottle`](https://usehooks-ts.com/react-hook/use-throttle) — A custom hooks that support throttle +- [`useThrottle`](https://usehooks-ts.com/react-hook/use-throttle) — A custom hooks that support throttle. - [`useTimeout`](https://usehooks-ts.com/react-hook/use-timeout) — handles timeouts in React components using the [setTimeout API](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout). - [`useToggle`](https://usehooks-ts.com/react-hook/use-toggle) — manages a boolean toggle state in React components. - [`useUnmount`](https://usehooks-ts.com/react-hook/use-unmount) — runs a cleanup function when the component is unmounted.