From 91ff6ba376fd2920133a5be3b238e36aa22253ae Mon Sep 17 00:00:00 2001 From: James Ivings Date: Tue, 18 Dec 2018 18:12:24 -0500 Subject: [PATCH] feat: added useDebounce --- docs/useDebounce.md | 46 +++++++++++++++++++++++++++ src/__stories__/useDebounce.story.tsx | 36 +++++++++++++++++++++ src/index.ts | 2 ++ src/useDebounce.ts | 14 ++++++++ 4 files changed, 98 insertions(+) create mode 100644 docs/useDebounce.md create mode 100644 src/__stories__/useDebounce.story.tsx create mode 100644 src/useDebounce.ts diff --git a/docs/useDebounce.md b/docs/useDebounce.md new file mode 100644 index 0000000000..52218e16b1 --- /dev/null +++ b/docs/useDebounce.md @@ -0,0 +1,46 @@ +# `useDebounce` + +React hook that delays invoking a function until after wait milliseconds have elapsed since the last time the debounced function was invoked. + +The third argument is the array of values that the debounce depends on, in the same manner as useEffect. The debounce timeout will start when one of the values changes. + +## Usage + +```jsx +import React, { useState } from 'react'; +import { useDebounce } from 'react-use'; + +const Demo = () => { + const [state, setState] = React.useState('Typing stopped'); + const [val, setVal] = React.useState(''); + + useDebounce( + () => { + setState('Typing stopped'); + }, + 2000, + [val] + ); + + return ( +
+ { + setState('Waiting for typing to stop...'); + setVal(currentTarget.value); + }} + /> +
{state}
+
+ ); +}; +``` + +## Reference + +```ts +useDebouce(fn, ms: number, args: any[]); +``` diff --git a/src/__stories__/useDebounce.story.tsx b/src/__stories__/useDebounce.story.tsx new file mode 100644 index 0000000000..e4a4104e65 --- /dev/null +++ b/src/__stories__/useDebounce.story.tsx @@ -0,0 +1,36 @@ +import * as React from 'react'; +import { storiesOf } from '@storybook/react'; +import { useDebounce } from '..'; +import ShowDocs from '../util/ShowDocs'; + +const Demo = () => { + const [state, setState] = React.useState('Typing stopped'); + const [val, setVal] = React.useState(''); + + useDebounce( + () => { + setState('Typing stopped'); + }, + 2000, + [val] + ); + + return ( +
+ { + setState('Waiting for typing to stop...'); + setVal(currentTarget.value); + }} + /> +
{state}
+
+ ); +}; + +storiesOf('Side effects/useDebounce', module) + .add('Docs', () => ) + .add('Demo', () => ); diff --git a/src/index.ts b/src/index.ts index 781f36dae5..85884f2d6e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,6 +6,7 @@ import useBoolean from './useBoolean'; import useCallbag from './useCallbag'; import useCounter from './useCounter'; import useCss from './useCss'; +import useDebounce from './useDebounce'; import useFavicon from './useFavicon'; import useGeolocation from './useGeolocation'; import useGetSet from './useGetSet'; @@ -54,6 +55,7 @@ export { useCallbag, useCounter, useCss, + useDebounce, useFavicon, useGeolocation, useGetSet, diff --git a/src/useDebounce.ts b/src/useDebounce.ts new file mode 100644 index 0000000000..43003c2704 --- /dev/null +++ b/src/useDebounce.ts @@ -0,0 +1,14 @@ +import { useState, useEffect } from 'react'; + +const useDebounce = (fn: () => any, ms: number = 0, args: Array = []) => { + const [timeout, setTimeoutVar] = useState(-1); + + useEffect(() => { + // if args change then clear timeout + clearTimeout(timeout); + const t = setTimeout(fn.bind(null, args), ms); + setTimeoutVar(t); + }, args); +}; + +export default useDebounce;