mirror of
https://github.com/streamich/react-use.git
synced 2026-01-18 14:06:52 +00:00
feat: add useThrottle hook
This commit is contained in:
commit
756bc992d4
@ -71,12 +71,13 @@
|
||||
- [**Side-effects**](./docs/Side-effects.md)
|
||||
- [`useAsync`](./docs/useAsync.md) — resolves an `async` function.
|
||||
- [`useAsyncRetry`](./docs/useAsyncRetry.md) — `useAsync` with `retry()` method.
|
||||
- [`useDebounce`](./docs/useDebounce.md) — debounces a function. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/side-effects-usedebounce--demo)
|
||||
- [`useFavicon`](./docs/useFavicon.md) — sets favicon of the page.
|
||||
- [`useLocalStorage`](./docs/useLocalStorage.md) — manages a value in `localStorage`.
|
||||
- [`useLockBodyScroll`](./docs/useLockBodyScroll.md) — lock scrolling of the body element.
|
||||
- [`useSessionStorage`](./docs/useSessionStorage.md) — manages a value in `sessionStorage`.
|
||||
- [`useThrottle`](./docs/useThrottle.md) — throttles a function. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/side-effects-usethrottle--demo)
|
||||
- [`useTitle`](./docs/useTitle.md) — sets title of the page.
|
||||
- [`useDebounce`](./docs/useDebounce.md) — debounces a function.
|
||||
<br/>
|
||||
<br/>
|
||||
- [**Lifecycles**](./docs/Lifecycles.md)
|
||||
|
||||
@ -13,10 +13,12 @@ import { useDebounce } from 'react-use';
|
||||
const Demo = () => {
|
||||
const [state, setState] = React.useState('Typing stopped');
|
||||
const [val, setVal] = React.useState('');
|
||||
const [debouncedValue, setDebouncedValue] = React.useState('');
|
||||
|
||||
useDebounce(
|
||||
() => {
|
||||
setState('Typing stopped');
|
||||
setDebouncedValue(val);
|
||||
},
|
||||
2000,
|
||||
[val]
|
||||
@ -34,6 +36,7 @@ const Demo = () => {
|
||||
}}
|
||||
/>
|
||||
<div>{state}</div>
|
||||
<div>Debounced value: {debouncedValue}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -42,5 +45,5 @@ const Demo = () => {
|
||||
## Reference
|
||||
|
||||
```ts
|
||||
useDebouce(fn, ms: number, args: any[]);
|
||||
useDebounce(fn, ms: number, args: any[]);
|
||||
```
|
||||
|
||||
49
docs/useThrottle.md
Normal file
49
docs/useThrottle.md
Normal file
@ -0,0 +1,49 @@
|
||||
# `useThrottle`
|
||||
|
||||
React hook that invokes a function and then delays subsequent function calls until after wait milliseconds have elapsed since the last time the throttled function was invoked.
|
||||
|
||||
The third argument is the array of values that the throttle depends on, in the same manner as useEffect. The throttle timeout will start when one of the values changes.
|
||||
|
||||
## Usage
|
||||
|
||||
```jsx
|
||||
import React, { useState } from 'react';
|
||||
import { useThrottle } from 'react-use';
|
||||
|
||||
const Demo = () => {
|
||||
const [status, setStatus] = React.useState('Updating stopped');
|
||||
const [value, setValue] = React.useState('');
|
||||
const [throttledValue, setThrottledValue] = React.useState('');
|
||||
|
||||
useThrottle(
|
||||
() => {
|
||||
setStatus('Waiting for input...');
|
||||
setThrottledValue(value);
|
||||
},
|
||||
2000,
|
||||
[value]
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
value={value}
|
||||
placeholder="Throttled input"
|
||||
onChange={({ currentTarget }) => {
|
||||
setStatus('Updating stopped');
|
||||
setValue(currentTarget.value);
|
||||
}}
|
||||
/>
|
||||
<div>{status}</div>
|
||||
<div>Throttled value: {throttledValue}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
```ts
|
||||
useThrottle(fn, ms: number, args: any[]);
|
||||
```
|
||||
@ -6,10 +6,12 @@ import ShowDocs from '../util/ShowDocs';
|
||||
const Demo = () => {
|
||||
const [state, setState] = React.useState('Typing stopped');
|
||||
const [val, setVal] = React.useState('');
|
||||
const [debouncedValue, setDebouncedValue] = React.useState('');
|
||||
|
||||
useDebounce(
|
||||
() => {
|
||||
setState('Typing stopped');
|
||||
setDebouncedValue(val);
|
||||
},
|
||||
2000,
|
||||
[val]
|
||||
@ -27,6 +29,7 @@ const Demo = () => {
|
||||
}}
|
||||
/>
|
||||
<div>{state}</div>
|
||||
<div>Debounced value: {debouncedValue}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
39
src/__stories__/useThrottle.story.tsx
Normal file
39
src/__stories__/useThrottle.story.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
import * as React from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { useThrottle } from '..';
|
||||
import ShowDocs from '../util/ShowDocs';
|
||||
|
||||
const Demo = () => {
|
||||
const [status, setStatus] = React.useState('Updating stopped');
|
||||
const [value, setValue] = React.useState('');
|
||||
const [throttledValue, setThrottledValue] = React.useState('');
|
||||
|
||||
useThrottle(
|
||||
() => {
|
||||
setStatus('Waiting for input...');
|
||||
setThrottledValue(value);
|
||||
},
|
||||
2000,
|
||||
[value]
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
value={value}
|
||||
placeholder="Throttled input"
|
||||
onChange={({ currentTarget }) => {
|
||||
setStatus('Updating stopped');
|
||||
setValue(currentTarget.value);
|
||||
}}
|
||||
/>
|
||||
<div>{status}</div>
|
||||
<div>Throttled value: {throttledValue}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
storiesOf('Side effects|useThrottle', module)
|
||||
.add('Docs', () => <ShowDocs md={require('../../docs/useThrottle.md')} />)
|
||||
.add('Demo', () => <Demo />);
|
||||
@ -43,6 +43,7 @@ import useSetState from './useSetState';
|
||||
import useSize from './useSize';
|
||||
import useSpeech from './useSpeech';
|
||||
import useSpring from './useSpring';
|
||||
import useThrottle from './useThrottle';
|
||||
import useTimeout from './useTimeout';
|
||||
import useTitle from './useTitle';
|
||||
import useToggle from './useToggle';
|
||||
@ -101,6 +102,7 @@ export {
|
||||
useSize,
|
||||
useSpeech,
|
||||
useSpring,
|
||||
useThrottle,
|
||||
useTimeout,
|
||||
useTitle,
|
||||
useToggle,
|
||||
|
||||
28
src/useThrottle.ts
Normal file
28
src/useThrottle.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { useRef, useEffect } from 'react';
|
||||
|
||||
const useThrottle = (fn: () => any, ms: number = 0, args?) => {
|
||||
const lastRan = useRef(0);
|
||||
|
||||
useEffect(() => {
|
||||
let timeout
|
||||
const diff = Date.now() - lastRan.current
|
||||
|
||||
if (diff >= ms) {
|
||||
fn.apply(null, args);
|
||||
lastRan.current = Date.now();
|
||||
} else {
|
||||
timeout = setTimeout(() => {
|
||||
fn.apply(null, args);
|
||||
lastRan.current = Date.now();
|
||||
}, ms - diff)
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
}
|
||||
}, args);
|
||||
};
|
||||
|
||||
export default useThrottle;
|
||||
Loading…
x
Reference in New Issue
Block a user