Skip to content

Commit ebf7dda

Browse files
committed
main 🧊 add thorttle hooks
1 parent 9ef00f6 commit ebf7dda

File tree

7 files changed

+131
-1
lines changed

7 files changed

+131
-1
lines changed

‎docs/.vitepress/config.mts

+9
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ export default async () => {
4040
}
4141
},
4242
transformPageData: (pageData) => {
43+
pageData.frontmatter.head ??= []
44+
pageData.frontmatter.head.push([
45+
'meta',
46+
{
47+
name: 'og:image',
48+
content: 'https://repository-images.githubusercontent.com/799880708/be8887a4-0cf5-4929-a5f0-dba8d70a7d1f'
49+
}
50+
])
51+
4352
if (pageData.relativePath === 'index.md') {
4453
pageData.frontmatter.features = homePageFeatures;
4554
}

‎src/hooks/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ export * from './useStopwatch/useStopwatch';
100100
export * from './useStorage/useStorage';
101101
export * from './useTextDirection/useTextDirection';
102102
export * from './useTextSelection/useTextSelection';
103+
export * from './useThrottleCallback/useThrottleCallback';
104+
export * from './useThrottleValue/useThrottleValue';
103105
export * from './useTime/useTime';
104106
export * from './useTimeout/useTimeout';
105107
export * from './useTimer/useTimer';

‎src/hooks/useDebounceCallback/useDebounceCallback.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { useEvent } from '../useEvent/useEvent';
1616
* @returns {(...args: Params) => Return} The callback with debounce
1717
*
1818
* @example
19-
* const debounced = useDebounceCallback(() => console.log('callback'), 500);
19+
* const debouncedCallback = useDebounceCallback(() => console.log('callback'), 500);
2020
*/
2121
export const useDebounceCallback = <Params extends unknown[], Return>(
2222
callback: (...args: Params) => Return,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { useCounter } from '../useCounter/useCounter';
2+
import { useThrottleCallback } from './useThrottleCallback';
3+
4+
const Demo = () => {
5+
const clickCounter = useCounter();
6+
const throttledCounter = useCounter();
7+
8+
9+
const throttledIncrement = useThrottleCallback(throttledCounter.inc, 1000);
10+
11+
const onClick = () => {
12+
throttledIncrement();
13+
clickCounter.inc();
14+
}
15+
16+
return (
17+
<div>
18+
<p>
19+
Button clicked: <code>{clickCounter.value}</code>
20+
</p>
21+
<p>
22+
Event handler called: <code>{throttledCounter.value}</code>
23+
</p>
24+
<p className='text-sm text-zinc-400'>Delay is set to 1000ms for this demo.</p>
25+
<button type='button' onClick={onClick}>
26+
Smash me my friend
27+
</button>
28+
</div>
29+
);
30+
};
31+
32+
export default Demo;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { useMemo } from 'react';
2+
3+
import { throttle } from '@/utils/helpers';
4+
5+
import { useEvent } from '../useEvent/useEvent';
6+
7+
/**
8+
* @name useThrottleCallback
9+
* @description - Hook that creates a throttled callback and returns a stable reference of it
10+
* @category Utilities
11+
*
12+
* @template Params The type of the params
13+
* @template Return The type of the return
14+
* @param {(...args: Params) => Return} callback The callback function
15+
* @param {number} delay The delay in milliseconds
16+
* @returns {(...args: Params) => Return} The callback with throttle
17+
*
18+
* @example
19+
* const throttled = useThrottleCallback(() => console.log('callback'), 500);
20+
*/
21+
export const useThrottleCallback = <Params extends unknown[], Return>(
22+
callback: (...args: Params) => Return,
23+
delay: number
24+
) => {
25+
const internalCallback = useEvent(callback);
26+
const throttled = useMemo(() => throttle(internalCallback, delay), [delay]);
27+
28+
return throttled;
29+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { useCounter } from '../useCounter/useCounter';
2+
import { useThrottleValue } from './useThrottleValue';
3+
4+
const Demo = () => {
5+
const counter = useCounter();
6+
7+
const throttledCounterCount = useThrottleValue(counter.value, 500);
8+
9+
return (
10+
<div>
11+
<p>
12+
Value: <code>{counter.value}</code>
13+
</p>
14+
<p>
15+
Throttled value: <code>{throttledCounterCount}</code>
16+
</p>
17+
<button type='button' onClick={() => counter.inc()}>
18+
Increment
19+
</button>
20+
<button type='button' onClick={() => counter.dec()}>
21+
Decrement
22+
</button>
23+
</div>
24+
);
25+
};
26+
27+
export default Demo;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { useEffect, useRef, useState } from 'react';
2+
3+
import { useThrottleCallback } from '../useThrottleCallback/useThrottleCallback';
4+
5+
/**
6+
* @name useThrottleValue
7+
* @description - Hook that creates a throttled value and returns a stable reference of it
8+
* @category Utilities
9+
*
10+
* @template Value The type of the value
11+
* @param {Value} value The value to be throttled
12+
* @param {number} delay The delay in milliseconds
13+
* @returns {Value} The throttled value
14+
*
15+
* @example
16+
* const throttledValue = useThrottleValue(value, 500);
17+
*/
18+
export const useThrottleValue = <Value>(value: Value, delay: number) => {
19+
const previousValueRef = useRef(value);
20+
const [throttledValue, setDebounceValue] = useState(value);
21+
22+
const throttledSetState = useThrottleCallback(setDebounceValue, delay);
23+
24+
useEffect(() => {
25+
if (previousValueRef.current === value) return;
26+
throttledSetState(value);
27+
previousValueRef.current = value;
28+
}, [value]);
29+
30+
return throttledValue;
31+
};

0 commit comments

Comments
 (0)