Skip to content

Commit 0ccdf95

Browse files
committed
feat: 🎸 add useThrottleFn hook that throttles function
This hook used to be called useThrottle, but it also was re-implemented.
1 parent 452e8d9 commit 0ccdf95

File tree

5 files changed

+84
-4
lines changed

5 files changed

+84
-4
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
- [`useLocalStorage`](./docs/useLocalStorage.md) — manages a value in `localStorage`.
7979
- [`useLockBodyScroll`](./docs/useLockBodyScroll.md) — lock scrolling of the body element.
8080
- [`useSessionStorage`](./docs/useSessionStorage.md) — manages a value in `sessionStorage`.
81-
- [`useThrottle`](./docs/useThrottle.md) — throttles a function. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/side-effects-usethrottle--demo)
81+
- [`useThrottle` and `useThrottleFn`](./docs/useThrottle.md) — throttles a function. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/side-effects-usethrottle--demo)
8282
- [`useTitle`](./docs/useTitle.md) — sets title of the page.
8383
<br/>
8484
<br/>

docs/useThrottle.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
# `useThrottle`
1+
# `useThrottle` and `useThrottleFn`
22

3-
React hook that throttles a value.
3+
React hooks that throttle.
44

55
## Usage
66

77
```jsx
88
import React, { useState } from 'react';
9-
import { useThrottle } from 'react-use';
9+
import { useThrottle, useThrottleFn } from 'react-use';
1010

1111
const Demo = ({value}) => {
1212
const throttledValue = useThrottle(value);
13+
// const throttledValue = useThrottleFn(value => value, 200, [value]);
1314

1415
return (
1516
<>
@@ -24,4 +25,5 @@ const Demo = ({value}) => {
2425

2526
```ts
2627
useThrottle(value, ms?: number);
28+
useThrottleFn(fn, ms, args);
2729
```
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import * as React from 'react';
2+
import { storiesOf } from '@storybook/react';
3+
import { useThrottleFn, useCounter } from '..';
4+
import ShowDocs from '../util/ShowDocs';
5+
6+
const Demo = () => {
7+
const [value, setValue] = React.useState('');
8+
const throttledValue = useThrottleFn(value => value, 2000, [value]);
9+
const [lastThrottledValue, setLastThrottledValue] = React.useState(throttledValue);
10+
const [count, {inc}] = useCounter();
11+
12+
React.useEffect(() => {
13+
if (lastThrottledValue !== throttledValue) {
14+
setLastThrottledValue(throttledValue);
15+
inc();
16+
}
17+
});
18+
19+
return (
20+
<div style={{width: 300, margin: '40px auto'}}>
21+
<input
22+
type="text"
23+
value={value}
24+
placeholder="Throttled input"
25+
style={{width: '100%'}}
26+
onChange={({ currentTarget }) => {
27+
setValue(currentTarget.value);
28+
}}
29+
/>
30+
<br />
31+
<br />
32+
<div>Throttled value: {throttledValue}</div>
33+
<div>Times updated: {count}</div>
34+
</div>
35+
);
36+
};
37+
38+
storiesOf('Side effects|useThrottleFn', module)
39+
.add('Docs', () => <ShowDocs md={require('../../docs/useThrottle.md')} />)
40+
.add('Demo', () => <Demo />);

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import useSize from './useSize';
4646
import useSpeech from './useSpeech';
4747
import useSpring from './useSpring';
4848
import useThrottle from './useThrottle';
49+
import useThrottleFn from './useThrottleFn';
4950
import useTimeout from './useTimeout';
5051
import useTitle from './useTitle';
5152
import useToggle from './useToggle';
@@ -107,6 +108,7 @@ export {
107108
useSpeech,
108109
useSpring,
109110
useThrottle,
111+
useThrottleFn,
110112
useTimeout,
111113
useTitle,
112114
useToggle,

src/useThrottleFn.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import {useState, useRef, useEffect} from 'react';
2+
import useUnmount from './useUnmount'
3+
4+
const useThrottleFn = <T>(fn: (...args: any[]) => T, ms: number = 200, args: any[]) => {
5+
const [state, setState] = useState<T>(null as any);
6+
let timeout = useRef<any>(null);
7+
const nextArgs = useRef(null) as any;
8+
const hasNextArgs = useRef(false) as any;
9+
10+
useEffect(() => {
11+
if (!timeout.current) {
12+
setState(fn(...args));
13+
const timeoutCallback = () => {
14+
if (hasNextArgs.current) {
15+
hasNextArgs.current = false;
16+
setState(fn(...nextArgs.current));
17+
timeout.current = setTimeout(timeoutCallback, ms);
18+
} else {
19+
timeout.current = null;
20+
}
21+
};
22+
timeout.current = setTimeout(timeoutCallback, ms);
23+
} else {
24+
nextArgs.current = args;
25+
hasNextArgs.current = true;
26+
}
27+
}, args);
28+
29+
useUnmount(() => {
30+
clearTimeout(timeout.current);
31+
});
32+
33+
return state;
34+
};
35+
36+
export default useThrottleFn;

0 commit comments

Comments
 (0)