Skip to content

Commit 6f71cda

Browse files
committed
feat: 🎸 Added state and effect hooks
1 parent c91217a commit 6f71cda

File tree

19 files changed

+286
-64
lines changed

19 files changed

+286
-64
lines changed

README.md

Lines changed: 133 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@
2626
<img src="https://custom-icon-badges.demolab.com/npm/dm/@better-hooks/performance?logoColor=fff&logo=trending-up" />
2727
</a>
2828
</p>
29+
2930
## About
3031

31-
Debounce and throttle your functions to gain performance boost!
32+
Debounce and throttle your functions, state and effects to gain performance boost!
3233

3334
## Key Features
3435

@@ -38,6 +39,10 @@ Debounce and throttle your functions to gain performance boost!
3839

3940
**Debounce and Throttle**
4041

42+
🎊 **Lifecycle debounce and throttle**
43+
44+
📡 **State debounce and throttle**
45+
4146
## Installation
4247

4348
```bash
@@ -56,14 +61,15 @@ yarn add @better-hooks/performance
5661

5762
#### useDebounce
5863

59-
This hook allows debouncing of the given function.
64+
This hook allows debouncing of the given function. Function will be called after some amount of time
65+
from the last execution. We can adjust debounce time with additional props.
6066

6167
```tsx
6268
import React from "react";
6369
import { useDebounce } from "@better-hooks/performance";
6470

65-
const MyComponent: React.FC = ({ delay }) => {
66-
const {debounce, reset, active} = useDebounce(delay)
71+
const MyComponent: React.FC = () => {
72+
const {debounce, reset, active} = useDebounce({ delay: 600 })
6773

6874
// Standard usage
6975
const onTyping = () => {
@@ -76,7 +82,7 @@ const MyComponent: React.FC = ({ delay }) => {
7682
const onTypingDynamic = (value: string, customDelay: number) => {
7783
debounce(() => {
7884
// debounced logic
79-
}, customDelay)
85+
}, { delay: customDelay })
8086
}
8187

8288
return (
@@ -86,6 +92,57 @@ const MyComponent: React.FC = ({ delay }) => {
8692

8793
```
8894

95+
---
96+
97+
#### useDebounceState
98+
99+
This hook allows debouncing of state. Value will be saved after some amount of time from the last
100+
execution of set function. We can adjust debounce time with additional props.
101+
102+
```tsx
103+
import React from "react";
104+
import { useWindowEvent } from "@better-hooks/window";
105+
import { useDebounceState } from "@better-hooks/performance";
106+
107+
const MyComponent: React.FC = () => {
108+
const [value, setValue] = useDebounceState("20px")
109+
110+
useWindowEvent("scroll", (e) => {
111+
setValue(e.scrollY + "px");
112+
})
113+
114+
return (
115+
// ...
116+
)
117+
}
118+
119+
```
120+
121+
---
122+
123+
#### useDebounceEffect
124+
125+
This hook allows debouncing of lifecycle effect.
126+
127+
```tsx
128+
import React from "react";
129+
import { useDebounceEffect } from "@better-hooks/performance";
130+
131+
const MyComponent: React.FC = (props) => {
132+
133+
useDebounceEffect(() => {
134+
// Do something
135+
}, { delay: 200 }, [props])
136+
137+
return (
138+
// ...
139+
)
140+
}
141+
142+
```
143+
144+
---
145+
89146
#### useThrottle
90147

91148
This hook allows debouncing of the given function.
@@ -117,3 +174,74 @@ const MyComponent: React.FC = ({ delay }) => {
117174
}
118175

119176
```
177+
178+
---
179+
180+
#### useThrottleState
181+
182+
This hook allows throttling of state. We can adjust execution interval time and execution timeout
183+
time with additional props.
184+
185+
```tsx
186+
import React from "react";
187+
import { useWindowEvent } from "@better-hooks/window";
188+
import { useThrottleState } from "@better-hooks/performance";
189+
190+
const MyComponent: React.FC = () => {
191+
const [value, setValue] = useThrottleState("20px")
192+
193+
useWindowEvent("scroll", (e) => {
194+
setValue(e.scrollY + "px");
195+
})
196+
197+
return (
198+
// ...
199+
)
200+
}
201+
202+
```
203+
204+
```tsx
205+
import React from "react";
206+
import { useWindowEvent } from "@better-hooks/window";
207+
import { useThrottleState } from "@better-hooks/performance";
208+
209+
const MyComponent: React.FC = () => {
210+
const [value, setValue] = useThrottleState("20px", {
211+
executionInterval: 200, // We will save values at least once per 200ms
212+
executionTimeout: 400 // Last set state action will get triggered after 400ms, we can also disable it
213+
})
214+
215+
useWindowEvent("scroll", (e) => {
216+
setValue(e.scrollY + "px");
217+
})
218+
219+
return (
220+
// ...
221+
)
222+
}
223+
224+
```
225+
226+
---
227+
228+
#### useThrottleEffect
229+
230+
This hook allows debouncing of lifecycle effect.
231+
232+
```tsx
233+
import React from "react";
234+
import { useThrottleEffect } from "@better-hooks/performance";
235+
236+
const MyComponent: React.FC = (props) => {
237+
238+
useThrottleEffect(() => {
239+
// Do something
240+
}, { executionInterval: 200, executionTimeout: false }, [props])
241+
242+
return (
243+
// ...
244+
)
245+
}
246+
247+
```

package.json

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -114,20 +114,14 @@
114114
"keywords": [
115115
"react",
116116
"hooks",
117-
"lifecycle",
118-
"use",
119-
"did",
120-
"mount",
121-
"update",
122-
"unmount",
123-
"render",
124-
"hook",
125-
"useDidMount",
126-
"useDidUnmount",
127-
"useDidRender",
128-
"useWillUnmount"
129-
],
130-
"dependencies": {
131-
"@better-typed/react-lifecycle-hooks": "^1.0.5"
132-
}
117+
"performance",
118+
"throttle",
119+
"debounce",
120+
"useDebounce",
121+
"useDebounceState",
122+
"useDebounceEffect",
123+
"useThrottle",
124+
"useThrottleState",
125+
"useThrottleEffect"
126+
]
133127
}

src/hooks/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
export * from "./use-debounce";
2+
export * from "./use-debounce-state";
3+
export * from "./use-debounce-effect";
24
export * from "./use-throttle";
5+
export * from "./use-throttle-state";
6+
export * from "./use-throttle-effect";
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./use-debounce-effect.hook";
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/* eslint-disable react-hooks/exhaustive-deps */
2+
import { useEffect } from "react";
3+
4+
import { useDebounce } from "hooks/use-debounce/use-debounce.hook";
5+
import { UseDebounceProps } from "hooks/use-debounce/use-debounce.types";
6+
7+
export const useDebounceEffect = (
8+
callback: () => void,
9+
props: UseDebounceProps,
10+
dependencies: any[],
11+
) => {
12+
const { debounce } = useDebounce(props);
13+
useEffect(() => {
14+
debounce(callback);
15+
}, dependencies);
16+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./use-debounce-state.hook";
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { useState } from "react";
2+
3+
import { useDebounce } from "hooks/use-debounce/use-debounce.hook";
4+
import { UseDebounceProps } from "hooks/use-debounce/use-debounce.types";
5+
6+
export const useDebounceState = <T>(initialValue: T, props?: UseDebounceProps) => {
7+
const { debounce } = useDebounce(props);
8+
const [value, setValue] = useState(initialValue);
9+
return [value, (newValue: Parameters<typeof setValue>[0]) => debounce(() => setValue(newValue))];
10+
};

src/hooks/use-debounce/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from "./use-debounce.hook";
2+
export * from "./use-debounce.types";

src/hooks/use-debounce.ts renamed to src/hooks/use-debounce/use-debounce.hook.ts

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,15 @@
1-
import { useRef } from "react";
2-
import { useWillUnmount, useForceUpdate } from "@better-typed/react-lifecycle-hooks";
1+
import { useEffect, useRef } from "react";
32

4-
type DebounceType = ReturnType<typeof setTimeout> | null;
5-
export type DebounceFunctionType = (
6-
callback: () => void | Promise<void>,
7-
dynamicDelay?: number,
8-
) => void;
9-
export type UseDebounceReturnType = {
10-
debounce: DebounceFunctionType;
11-
reset: VoidFunction;
12-
active: boolean;
13-
};
3+
import {
4+
DebounceType,
5+
UseDebounceProps,
6+
DebounceFunctionType,
7+
UseDebounceReturnType,
8+
} from "./use-debounce.types";
9+
import { useForceUpdate } from "hooks/use-force-update";
1410

15-
/**
16-
* @param delay
17-
* @internal
18-
* @returns
19-
*/
20-
export const useDebounce = (delay = 400): UseDebounceReturnType => {
11+
export const useDebounce = (props?: UseDebounceProps): UseDebounceReturnType => {
12+
const { delay = 400 } = props || {};
2113
const shouldRerenderActive = useRef(false);
2214
const timer = useRef<DebounceType>(null);
2315
const forceUpdate = useForceUpdate();
@@ -42,7 +34,9 @@ export const useDebounce = (delay = 400): UseDebounceReturnType => {
4234
rerenderActive();
4335
};
4436

45-
useWillUnmount(reset);
37+
useEffect(() => {
38+
return reset;
39+
}, []);
4640

4741
return {
4842
get active() {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export type DebounceType = ReturnType<typeof setTimeout> | null;
2+
3+
export type DebounceFunctionType = (
4+
callback: () => void | Promise<void>,
5+
dynamicDelay?: number,
6+
) => void;
7+
8+
export type UseDebounceReturnType = {
9+
debounce: DebounceFunctionType;
10+
reset: VoidFunction;
11+
active: boolean;
12+
};
13+
14+
export type UseDebounceProps = {
15+
delay?: number;
16+
};

0 commit comments

Comments
 (0)