@alessiofrittoli/react-hooks 3.4.0 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +804 -650
- package/dist/index.d.mts +165 -1
- package/dist/index.d.ts +165 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
[downloads-badge]: https://img.shields.io/npm/dm/%40alessiofrittoli%2Freact-hooks.svg
|
|
14
14
|
[deps-badge]: https://img.shields.io/librariesio/release/npm/%40alessiofrittoli%2Freact-hooks
|
|
15
15
|
[deps-url]: https://libraries.io/npm/%40alessiofrittoli%2Freact-hooks
|
|
16
|
-
|
|
17
16
|
[sponsor-badge]: https://img.shields.io/static/v1?label=Fund%20this%20package&message=%E2%9D%A4&logo=GitHub&color=%23DB61A2
|
|
18
17
|
[sponsor-url]: https://github.com/sponsors/alessiofrittoli
|
|
19
18
|
|
|
@@ -33,7 +32,10 @@
|
|
|
33
32
|
- [`useDarkMode`](#usedarkmode)
|
|
34
33
|
- [`useEventListener`](#useeventlistener)
|
|
35
34
|
- [`useIsPortrait`](#useisportrait)
|
|
35
|
+
- [`useIsTouchDevice`](#useistouchdevice)
|
|
36
36
|
- [`useMediaQuery`](#usemediaquery)
|
|
37
|
+
- [`useDocumentVisibility`](#usedocumentvisibility)
|
|
38
|
+
- [`useWakeLock`](#usewakelock)
|
|
37
39
|
- [DOM API](#dom-api)
|
|
38
40
|
- [`useFocusTrap`](#usefocustrap)
|
|
39
41
|
- [`useInView`](#useinview)
|
|
@@ -88,16 +90,15 @@ This library may define and exports hooks that requires additional ESLint config
|
|
|
88
90
|
Simply imports recommended configuration from `@alessiofrittoli/react-hooks/eslint` and add them to your ESLint configuration like so:
|
|
89
91
|
|
|
90
92
|
```mjs
|
|
91
|
-
import { config as AFReactHooksEslint } from
|
|
93
|
+
import { config as AFReactHooksEslint } from "@alessiofrittoli/react-hooks/eslint";
|
|
92
94
|
|
|
93
95
|
/** @type {import('eslint').Linter.Config[]} */
|
|
94
96
|
const config = [
|
|
95
97
|
...AFReactHooksEslint.recommended,
|
|
96
98
|
// ... other configurations
|
|
97
|
-
]
|
|
98
|
-
|
|
99
|
+
];
|
|
99
100
|
|
|
100
|
-
export default config
|
|
101
|
+
export default config;
|
|
101
102
|
```
|
|
102
103
|
|
|
103
104
|
---
|
|
@@ -106,8 +107,9 @@ export default config
|
|
|
106
107
|
|
|
107
108
|
#### Updates in the latest release 🎉
|
|
108
109
|
|
|
109
|
-
-
|
|
110
|
-
-
|
|
110
|
+
- Added `useDocumentVisibility`. See [API Reference](#usedocumentvisibility) for more info.
|
|
111
|
+
- Added `useWakeLock`. See [API Reference](#usewakelock) for more info.
|
|
112
|
+
- Added `useDeferCallback`. See [API Reference](#usedefercallback) for more info.
|
|
111
113
|
|
|
112
114
|
---
|
|
113
115
|
|
|
@@ -127,8 +129,8 @@ Easly handle Local or Session Storage State.
|
|
|
127
129
|
|
|
128
130
|
<summary style="cursor:pointer">Type parameters</summary>
|
|
129
131
|
|
|
130
|
-
| Parameter | Type
|
|
131
|
-
|
|
132
|
+
| Parameter | Type | Default | Description |
|
|
133
|
+
| --------- | ----- | -------- | ----------------------------------------- |
|
|
132
134
|
| `T` | `any` | `string` | A custom type applied to the stored item. |
|
|
133
135
|
|
|
134
136
|
</details>
|
|
@@ -139,11 +141,11 @@ Easly handle Local or Session Storage State.
|
|
|
139
141
|
|
|
140
142
|
<summary style="cursor:pointer">Parameters</summary>
|
|
141
143
|
|
|
142
|
-
| Parameter | Type
|
|
143
|
-
|
|
144
|
-
| `key` | `string`
|
|
145
|
-
| `initial` | `T`
|
|
146
|
-
| `type` | `local\|session`
|
|
144
|
+
| Parameter | Type | Default | Description |
|
|
145
|
+
| --------- | ---------------- | ------- | ---------------------------------- |
|
|
146
|
+
| `key` | `string` | - | The storage item key. |
|
|
147
|
+
| `initial` | `T` | - | The storage item initial value. |
|
|
148
|
+
| `type` | `local\|session` | local | (Optional) The storage API to use. |
|
|
147
149
|
|
|
148
150
|
</details>
|
|
149
151
|
|
|
@@ -169,8 +171,10 @@ A tuple with the stored item value or initial value and the setter function.
|
|
|
169
171
|
|
|
170
172
|
```tsx
|
|
171
173
|
import {
|
|
172
|
-
useStorage,
|
|
173
|
-
|
|
174
|
+
useStorage,
|
|
175
|
+
useLocalStorage,
|
|
176
|
+
useSessionStorage,
|
|
177
|
+
} from "@alessiofrittoli/react-hooks";
|
|
174
178
|
```
|
|
175
179
|
|
|
176
180
|
---
|
|
@@ -302,7 +306,6 @@ An object with the following properties:
|
|
|
302
306
|
|
|
303
307
|
---
|
|
304
308
|
|
|
305
|
-
|
|
306
309
|
##### `useDarkMode`
|
|
307
310
|
|
|
308
311
|
Easily manage dark mode with full respect for user device preferences.
|
|
@@ -317,11 +320,11 @@ This hook is user-oriented and built to honor system-level color scheme settings
|
|
|
317
320
|
|
|
318
321
|
<summary style="cursor:pointer">Parameters</summary>
|
|
319
322
|
|
|
320
|
-
| Parameter
|
|
321
|
-
|
|
322
|
-
| `options`
|
|
323
|
-
| `options.initial`
|
|
324
|
-
| `options.docClassNames` | `[dark: string, light: string]` | (Optional) Array of class names to toggle on the `<html>` element, e.g. `['dark', 'light']`.
|
|
323
|
+
| Parameter | Type | Description |
|
|
324
|
+
| ----------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
325
|
+
| `options` | `UseDarkModeOptions` | (Optional) Configuration object for the hook. |
|
|
326
|
+
| `options.initial` | `boolean` | (Optional) The fallback value to use if no preference is saved in `localStorage`. Defaults to `true` if the device prefers dark mode. |
|
|
327
|
+
| `options.docClassNames` | `[dark: string, light: string]` | (Optional) Array of class names to toggle on the `<html>` element, e.g. `['dark', 'light']`. |
|
|
325
328
|
|
|
326
329
|
</details>
|
|
327
330
|
|
|
@@ -352,17 +355,15 @@ An object containing utilities for managing dark mode:
|
|
|
352
355
|
###### Basic usage
|
|
353
356
|
|
|
354
357
|
```tsx
|
|
355
|
-
|
|
358
|
+
"use client";
|
|
356
359
|
|
|
357
|
-
import { useDarkMode } from
|
|
360
|
+
import { useDarkMode } from "@alessiofrittoli/react-hooks";
|
|
358
361
|
|
|
359
362
|
export const Component: React.FC = () => {
|
|
360
|
-
const { isDarkMode } = useDarkMode()
|
|
363
|
+
const { isDarkMode } = useDarkMode();
|
|
361
364
|
|
|
362
|
-
return
|
|
363
|
-
|
|
364
|
-
)
|
|
365
|
-
}
|
|
365
|
+
return <div>{isDarkMode ? "Dark mode enabled" : "Dark mode disabled"}</div>;
|
|
366
|
+
};
|
|
366
367
|
```
|
|
367
368
|
|
|
368
369
|
---
|
|
@@ -371,19 +372,17 @@ export const Component: React.FC = () => {
|
|
|
371
372
|
|
|
372
373
|
```tsx
|
|
373
374
|
// Component.tsx
|
|
374
|
-
|
|
375
|
+
"use client";
|
|
375
376
|
|
|
376
|
-
import { useDarkMode } from
|
|
377
|
+
import { useDarkMode } from "@alessiofrittoli/react-hooks";
|
|
377
378
|
|
|
378
379
|
export const Component: React.FC = () => {
|
|
379
|
-
const { isDarkMode } = useDarkMode(
|
|
380
|
-
docClassNames: [
|
|
381
|
-
}
|
|
380
|
+
const { isDarkMode } = useDarkMode({
|
|
381
|
+
docClassNames: ["dark", "light"],
|
|
382
|
+
});
|
|
382
383
|
|
|
383
|
-
return
|
|
384
|
-
|
|
385
|
-
)
|
|
386
|
-
}
|
|
384
|
+
return <div>{isDarkMode ? "Dark mode enabled" : "Dark mode disabled"}</div>;
|
|
385
|
+
};
|
|
387
386
|
```
|
|
388
387
|
|
|
389
388
|
```css
|
|
@@ -396,15 +395,13 @@ export const Component: React.FC = () => {
|
|
|
396
395
|
color-scheme: dark;
|
|
397
396
|
}
|
|
398
397
|
|
|
399
|
-
.light body
|
|
400
|
-
|
|
401
|
-
color : black;
|
|
398
|
+
.light body {
|
|
399
|
+
color: black;
|
|
402
400
|
background: white;
|
|
403
401
|
}
|
|
404
402
|
|
|
405
|
-
.dark body
|
|
406
|
-
|
|
407
|
-
color : white;
|
|
403
|
+
.dark body {
|
|
404
|
+
color: white;
|
|
408
405
|
background: black;
|
|
409
406
|
}
|
|
410
407
|
```
|
|
@@ -414,19 +411,15 @@ export const Component: React.FC = () => {
|
|
|
414
411
|
###### Custom theme switcher
|
|
415
412
|
|
|
416
413
|
```tsx
|
|
417
|
-
|
|
414
|
+
"use client";
|
|
418
415
|
|
|
419
|
-
import { useDarkMode } from
|
|
416
|
+
import { useDarkMode } from "@alessiofrittoli/react-hooks";
|
|
420
417
|
|
|
421
418
|
export const ThemeSwitcher: React.FC = () => {
|
|
422
|
-
const { isDarkMode, toggleDarkMode } = useDarkMode()
|
|
419
|
+
const { isDarkMode, toggleDarkMode } = useDarkMode();
|
|
423
420
|
|
|
424
|
-
return
|
|
425
|
-
|
|
426
|
-
{ isDarkMode ? '🌙' : '☀️' }
|
|
427
|
-
</button>
|
|
428
|
-
)
|
|
429
|
-
}
|
|
421
|
+
return <button onClick={toggleDarkMode}>{isDarkMode ? "🌙" : "☀️"}</button>;
|
|
422
|
+
};
|
|
430
423
|
```
|
|
431
424
|
|
|
432
425
|
---
|
|
@@ -436,10 +429,10 @@ export const ThemeSwitcher: React.FC = () => {
|
|
|
436
429
|
Browsers automatically apply colorization using:
|
|
437
430
|
|
|
438
431
|
```html
|
|
439
|
-
<meta name=
|
|
432
|
+
<meta name="theme-color" media="(prefers-color-scheme: dark)" />
|
|
440
433
|
```
|
|
441
434
|
|
|
442
|
-
This works based on the OS preference —
|
|
435
|
+
This works based on the OS preference — _not your site theme_. That can cause mismatches if, for example, the system is in dark mode but the user disabled dark mode via a web toggle.
|
|
443
436
|
|
|
444
437
|
To ensure consistency, `useDarkMode` updates these meta tags dynamically based on the actual mode.
|
|
445
438
|
|
|
@@ -447,8 +440,16 @@ Just make sure to define both `light` and `dark` theme-color tags in your docume
|
|
|
447
440
|
|
|
448
441
|
```html
|
|
449
442
|
<head>
|
|
450
|
-
<meta
|
|
451
|
-
|
|
443
|
+
<meta
|
|
444
|
+
name="theme-color"
|
|
445
|
+
media="(prefers-color-scheme: light)"
|
|
446
|
+
content="lime"
|
|
447
|
+
/>
|
|
448
|
+
<meta
|
|
449
|
+
name="theme-color"
|
|
450
|
+
media="(prefers-color-scheme: dark)"
|
|
451
|
+
content="aqua"
|
|
452
|
+
/>
|
|
452
453
|
</head>
|
|
453
454
|
```
|
|
454
455
|
|
|
@@ -468,14 +469,14 @@ Attach a new Event listener to the `Window`, `Document`, `MediaQueryList` or an
|
|
|
468
469
|
|
|
469
470
|
<summary style="cursor:pointer">Window events</summary>
|
|
470
471
|
|
|
471
|
-
| Parameter
|
|
472
|
-
|
|
473
|
-
| `type`
|
|
474
|
-
| `options`
|
|
475
|
-
| `options.listener`
|
|
476
|
-
| `options.onLoad`
|
|
477
|
-
| `options.onCleanUp` | `() => void`
|
|
478
|
-
| `options.options`
|
|
472
|
+
| Parameter | Type | Description |
|
|
473
|
+
| ------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
474
|
+
| `type` | `K\|K[]` | The `Window` event name or an array of event names. |
|
|
475
|
+
| `options` | `WindowListenerOptions<K>` | An object defining init options. |
|
|
476
|
+
| `options.listener` | `WindowEventListener<K>` | The Window Event listener. |
|
|
477
|
+
| `options.onLoad` | `() => void` | A custom callback executed before event listener get attached. |
|
|
478
|
+
| `options.onCleanUp` | `() => void` | A custom callback executed after event listener get removed. |
|
|
479
|
+
| `options.options` | `ListenerOptions` | Specifies characteristics about the event listener. See [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options). |
|
|
479
480
|
|
|
480
481
|
</details>
|
|
481
482
|
|
|
@@ -485,15 +486,15 @@ Attach a new Event listener to the `Window`, `Document`, `MediaQueryList` or an
|
|
|
485
486
|
|
|
486
487
|
<summary style="cursor:pointer">Document events</summary>
|
|
487
488
|
|
|
488
|
-
| Parameter
|
|
489
|
-
|
|
490
|
-
| `type`
|
|
491
|
-
| `options`
|
|
492
|
-
| `options.target`
|
|
493
|
-
| `options.listener`
|
|
494
|
-
| `options.onLoad`
|
|
495
|
-
| `options.onCleanUp` | `() => void`
|
|
496
|
-
| `options.options`
|
|
489
|
+
| Parameter | Type | Description |
|
|
490
|
+
| ------------------- | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
491
|
+
| `type` | `K\|K[]` | The `Document` event name or an array of event names. |
|
|
492
|
+
| `options` | `DocumentListenerOptions<K>` | An object defining init options. |
|
|
493
|
+
| `options.target` | `Document\|null\|React.RefObject<Document\|null>` | The `Document` reference or a React RefObject of the `Document`. |
|
|
494
|
+
| `options.listener` | `DocumentEventListener<K>` | The Document Event listener. |
|
|
495
|
+
| `options.onLoad` | `() => void` | A custom callback executed before event listener get attached. |
|
|
496
|
+
| `options.onCleanUp` | `() => void` | A custom callback executed after event listener get removed. |
|
|
497
|
+
| `options.options` | `ListenerOptions` | Specifies characteristics about the event listener. See [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options). |
|
|
497
498
|
|
|
498
499
|
</details>
|
|
499
500
|
|
|
@@ -503,15 +504,15 @@ Attach a new Event listener to the `Window`, `Document`, `MediaQueryList` or an
|
|
|
503
504
|
|
|
504
505
|
<summary style="cursor:pointer">HTMLElement events</summary>
|
|
505
506
|
|
|
506
|
-
| Parameter
|
|
507
|
-
|
|
508
|
-
| `type`
|
|
509
|
-
| `options`
|
|
510
|
-
| `options.target`
|
|
511
|
-
| `options.listener`
|
|
512
|
-
| `options.onLoad`
|
|
513
|
-
| `options.onCleanUp` | `() => void`
|
|
514
|
-
| `options.options`
|
|
507
|
+
| Parameter | Type | Description |
|
|
508
|
+
| ------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
509
|
+
| `type` | `K\|K[]` | The `HTMLElement` event name or an array of event names. |
|
|
510
|
+
| `options` | `ElementListenerOptions<K>` | An object defining init options. |
|
|
511
|
+
| `options.target` | `T\|React.RefObject<T\| null>` | The React RefObject of the target where the listener get attached to. |
|
|
512
|
+
| `options.listener` | `ElementEventListener<K>` | The HTMLElement Event listener. |
|
|
513
|
+
| `options.onLoad` | `() => void` | A custom callback executed before event listener get attached. |
|
|
514
|
+
| `options.onCleanUp` | `() => void` | A custom callback executed after event listener get removed. |
|
|
515
|
+
| `options.options` | `ListenerOptions` | Specifies characteristics about the event listener. See [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options). |
|
|
515
516
|
|
|
516
517
|
</details>
|
|
517
518
|
|
|
@@ -521,15 +522,15 @@ Attach a new Event listener to the `Window`, `Document`, `MediaQueryList` or an
|
|
|
521
522
|
|
|
522
523
|
<summary style="cursor:pointer">MediaQuery events</summary>
|
|
523
524
|
|
|
524
|
-
| Parameter
|
|
525
|
-
|
|
526
|
-
| `type`
|
|
527
|
-
| `options`
|
|
528
|
-
| `options.query`
|
|
529
|
-
| `options.listener`
|
|
530
|
-
| `options.onLoad`
|
|
531
|
-
| `options.onCleanUp` | `() => void`
|
|
532
|
-
| `options.options`
|
|
525
|
+
| Parameter | Type | Description |
|
|
526
|
+
| ------------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
527
|
+
| `type` | `change` | The `MediaQueryList` event name. |
|
|
528
|
+
| `options` | `MediaQueryListenerOptions` | An object defining init options. |
|
|
529
|
+
| `options.query` | `string` | The Media Query string to check. |
|
|
530
|
+
| `options.listener` | `MediaQueryChangeListener` | The MediaQueryList Event listener. |
|
|
531
|
+
| `options.onLoad` | `() => void` | A custom callback executed before event listener get attached. |
|
|
532
|
+
| `options.onCleanUp` | `() => void` | A custom callback executed after event listener get removed. |
|
|
533
|
+
| `options.options` | `ListenerOptions` | Specifies characteristics about the event listener. See [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options). |
|
|
533
534
|
|
|
534
535
|
</details>
|
|
535
536
|
|
|
@@ -539,15 +540,15 @@ Attach a new Event listener to the `Window`, `Document`, `MediaQueryList` or an
|
|
|
539
540
|
|
|
540
541
|
<summary style="cursor:pointer">Custom events</summary>
|
|
541
542
|
|
|
542
|
-
| Parameter
|
|
543
|
-
|
|
544
|
-
| `type`
|
|
545
|
-
| `options`
|
|
546
|
-
| `options.target`
|
|
547
|
-
| `options.listener`
|
|
548
|
-
| `options.onLoad`
|
|
549
|
-
| `options.onCleanUp` | `() => void`
|
|
550
|
-
| `options.options`
|
|
543
|
+
| Parameter | Type | Description |
|
|
544
|
+
| ------------------- | --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
545
|
+
| `type` | `K\|K[]` | The custom event name or an array of event names. |
|
|
546
|
+
| `options` | `CustomEventListenerOptions<T, K>` | An object defining init options. |
|
|
547
|
+
| `options.target` | `Document\|HTMLElement\|null\|React.RefObject<Document\|HTMLElement\|null>` | (Optional) The target where the listener get attached to. If not set, the listener will get attached to the `Window` object. |
|
|
548
|
+
| `options.listener` | `( event: T[ K ] ) => void` | The Event listener. |
|
|
549
|
+
| `options.onLoad` | `() => void` | A custom callback executed before event listener get attached. |
|
|
550
|
+
| `options.onCleanUp` | `() => void` | A custom callback executed after event listener get removed. |
|
|
551
|
+
| `options.options` | `ListenerOptions` | Specifies characteristics about the event listener. See [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#options). |
|
|
551
552
|
|
|
552
553
|
</details>
|
|
553
554
|
|
|
@@ -730,9 +731,40 @@ Type: `boolean`
|
|
|
730
731
|
###### Check if user device is in landscape
|
|
731
732
|
|
|
732
733
|
```tsx
|
|
733
|
-
import { useIsPortrait } from
|
|
734
|
+
import { useIsPortrait } from "@alessiofrittoli/react-hooks";
|
|
735
|
+
|
|
736
|
+
const isLandscape = !useIsPortrait();
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
</details>
|
|
740
|
+
|
|
741
|
+
---
|
|
742
|
+
|
|
743
|
+
##### `useIsTouchDevice`
|
|
744
|
+
|
|
745
|
+
Detects if the current device supports touch events.
|
|
746
|
+
|
|
747
|
+
<details>
|
|
748
|
+
|
|
749
|
+
<summary style="cursor:pointer">Returns</summary>
|
|
750
|
+
|
|
751
|
+
Type: `boolean`
|
|
752
|
+
|
|
753
|
+
- `true` if the device is touch device.
|
|
754
|
+
- `false` otherwise.
|
|
755
|
+
|
|
756
|
+
</details>
|
|
757
|
+
|
|
758
|
+
---
|
|
759
|
+
|
|
760
|
+
<details>
|
|
761
|
+
|
|
762
|
+
<summary style="cursor:pointer">Usage</summary>
|
|
763
|
+
|
|
764
|
+
```tsx
|
|
765
|
+
import { useIsTouchDevice } from "@alessiofrittoli/react-hooks";
|
|
734
766
|
|
|
735
|
-
const
|
|
767
|
+
const isTouchDevice = useIsTouchDevice();
|
|
736
768
|
```
|
|
737
769
|
|
|
738
770
|
</details>
|
|
@@ -747,13 +779,13 @@ Get Document Media matches and listen for changes.
|
|
|
747
779
|
|
|
748
780
|
<summary style="cursor:pointer">Parameters</summary>
|
|
749
781
|
|
|
750
|
-
| Parameter
|
|
751
|
-
|
|
752
|
-
| `query`
|
|
753
|
-
| `options`
|
|
754
|
-
| `options.updateState` | `boolean`
|
|
755
|
-
| `options.onChange`
|
|
756
|
-
|
|
|
782
|
+
| Parameter | Type | Default | Description |
|
|
783
|
+
| --------------------- | ------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
784
|
+
| `query` | `string` | - | A string specifying the media query to parse into a `MediaQueryList`. |
|
|
785
|
+
| `options` | `UseMediaQueryOptions\|UseMediaQueryStateOptions` | - | An object defining custom options. |
|
|
786
|
+
| `options.updateState` | `boolean` | `true` | Indicates whether the hook will dispatch a React state update when the given `query` change event get dispatched. |
|
|
787
|
+
| `options.onChange` | `OnChangeHandler` | - | A custom callback that will be invoked on initial page load and when the given `query` change event get dispatched. |
|
|
788
|
+
| | | | This callback is required if `updateState` is set to `false`. |
|
|
757
789
|
|
|
758
790
|
</details>
|
|
759
791
|
|
|
@@ -779,9 +811,9 @@ Type: `boolean|void`
|
|
|
779
811
|
###### Check if user device prefers dark color scheme
|
|
780
812
|
|
|
781
813
|
```tsx
|
|
782
|
-
import { useMediaQuery } from
|
|
814
|
+
import { useMediaQuery } from "@alessiofrittoli/react-hooks";
|
|
783
815
|
|
|
784
|
-
const isDarkOS = useMediaQuery(
|
|
816
|
+
const isDarkOS = useMediaQuery("(prefers-color-scheme: dark)");
|
|
785
817
|
```
|
|
786
818
|
|
|
787
819
|
---
|
|
@@ -789,14 +821,174 @@ const isDarkOS = useMediaQuery( '(prefers-color-scheme: dark)' )
|
|
|
789
821
|
###### Listen changes with no state updates
|
|
790
822
|
|
|
791
823
|
```tsx
|
|
792
|
-
import { useMediaQuery } from
|
|
824
|
+
import { useMediaQuery } from "@alessiofrittoli/react-hooks";
|
|
793
825
|
|
|
794
|
-
useMediaQuery(
|
|
826
|
+
useMediaQuery("(prefers-color-scheme: dark)", {
|
|
795
827
|
updateState: false,
|
|
796
|
-
onChange(
|
|
797
|
-
console.log(
|
|
798
|
-
}
|
|
799
|
-
}
|
|
828
|
+
onChange(matches) {
|
|
829
|
+
console.log("is dark OS?", matches);
|
|
830
|
+
},
|
|
831
|
+
});
|
|
832
|
+
```
|
|
833
|
+
|
|
834
|
+
</details>
|
|
835
|
+
|
|
836
|
+
---
|
|
837
|
+
|
|
838
|
+
##### `useDocumentVisibility`
|
|
839
|
+
|
|
840
|
+
Track the visibility state of the document (i.e., whether the page is visible or hidden).
|
|
841
|
+
|
|
842
|
+
<details>
|
|
843
|
+
|
|
844
|
+
<summary style="cursor:pointer">Parameters</summary>
|
|
845
|
+
|
|
846
|
+
| Parameter | Type | Default | Description |
|
|
847
|
+
| ---------------------------- | ------------------------------------------------------------------------- | ------- | --------------------------------------------------------------------- |
|
|
848
|
+
| `options` | `UseDocumentVisibilityOptions\|StateDisabledUseDocumentVisibilityOptions` | - | Configuration options for the hook. |
|
|
849
|
+
| `options.updateState` | `boolean` | `true` | Whether to update React state about Document visibility state or not. |
|
|
850
|
+
| `options.onVisibilityChange` | `VisibilityChangeHandler` | - | A custom callback executed when Document visiblity sate changes. |
|
|
851
|
+
|
|
852
|
+
</details>
|
|
853
|
+
|
|
854
|
+
---
|
|
855
|
+
|
|
856
|
+
<details>
|
|
857
|
+
|
|
858
|
+
<summary style="cursor:pointer">Returns</summary>
|
|
859
|
+
|
|
860
|
+
Type: `boolean | void`
|
|
861
|
+
|
|
862
|
+
Returns `true` if the document is visible, `false` if hidden, or `void` if `updateState` is set to `false`.
|
|
863
|
+
|
|
864
|
+
</details>
|
|
865
|
+
|
|
866
|
+
---
|
|
867
|
+
|
|
868
|
+
<details>
|
|
869
|
+
|
|
870
|
+
<summary style="cursor:pointer">Usage</summary>
|
|
871
|
+
|
|
872
|
+
###### Simple usage
|
|
873
|
+
|
|
874
|
+
```tsx
|
|
875
|
+
import { useDocumentVisibility } from "@alessiofrittoli/react-hooks";
|
|
876
|
+
|
|
877
|
+
const isDocumentVisible = useDocumentVisibility();
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
---
|
|
881
|
+
|
|
882
|
+
###### Disable state updates and listen visibility changes
|
|
883
|
+
|
|
884
|
+
```tsx
|
|
885
|
+
import {
|
|
886
|
+
useDocumentVisibility,
|
|
887
|
+
type VisibilityChangeHandler,
|
|
888
|
+
} from "@alessiofrittoli/react-hooks";
|
|
889
|
+
|
|
890
|
+
const onVisibilityChange = useCallback<VisibilityChangeHandler>((isVisible) => {
|
|
891
|
+
// ... do something
|
|
892
|
+
}, []);
|
|
893
|
+
useDocumentVisibility({ updateState: false, onVisibilityChange });
|
|
894
|
+
```
|
|
895
|
+
|
|
896
|
+
</details>
|
|
897
|
+
|
|
898
|
+
---
|
|
899
|
+
|
|
900
|
+
##### `useWakeLock`
|
|
901
|
+
|
|
902
|
+
Easily manage the [Screen Wake Lock API](https://developer.mozilla.org/en-US/docs/Web/API/Screen_Wake_Lock_API) to prevent the device screen from dimming or locking while your app is in use.
|
|
903
|
+
|
|
904
|
+
<details>
|
|
905
|
+
|
|
906
|
+
<summary style="cursor:pointer">Parameters</summary>
|
|
907
|
+
|
|
908
|
+
| Parameter | Type | Default | Description |
|
|
909
|
+
| ----------------- | ------------------------ | ------- | ---------------------------------------------------------------- |
|
|
910
|
+
| `options` | `UseWakeLockOptions` | - | (Optional) An object defining hook options. |
|
|
911
|
+
| `options.onMount` | `boolean` | `true` | Indicates whether to request the screen WakeLock on mount. |
|
|
912
|
+
| `options.onError` | `OnWakeLockRequestError` | - | A custom callback executed when a screen WakeLock request fails. |
|
|
913
|
+
|
|
914
|
+
</details>
|
|
915
|
+
|
|
916
|
+
---
|
|
917
|
+
|
|
918
|
+
<details>
|
|
919
|
+
|
|
920
|
+
<summary style="cursor:pointer">Returns</summary>
|
|
921
|
+
|
|
922
|
+
Type: `UseWakeLock`
|
|
923
|
+
|
|
924
|
+
An object returning The current `WakeLockSentinel` instance or `null` if not enabled and utility functions.
|
|
925
|
+
|
|
926
|
+
- `wakeLock`: `WakeLockSentinel | null` — The current Wake Lock instance, or null if not enabled.
|
|
927
|
+
- `enabled`: `boolean` — Whether the Wake Lock is currently active.
|
|
928
|
+
- `requestWakeLock`: `() => Promise<void>` — Manually request the Wake Lock.
|
|
929
|
+
- `releaseWakeLock`: `() => Promise<void>` — Manually release the Wake Lock.
|
|
930
|
+
|
|
931
|
+
</details>
|
|
932
|
+
|
|
933
|
+
---
|
|
934
|
+
|
|
935
|
+
<details>
|
|
936
|
+
|
|
937
|
+
<summary style="cursor:pointer">Usage</summary>
|
|
938
|
+
|
|
939
|
+
###### Enable Wake Lock on mount
|
|
940
|
+
|
|
941
|
+
```tsx
|
|
942
|
+
import { useWakeLock } from "@alessiofrittoli/react-hooks";
|
|
943
|
+
|
|
944
|
+
useWakeLock();
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
---
|
|
948
|
+
|
|
949
|
+
###### Manually enable and disable Wake Lock
|
|
950
|
+
|
|
951
|
+
```tsx
|
|
952
|
+
import { useWakeLock } from "@alessiofrittoli/react-hooks";
|
|
953
|
+
|
|
954
|
+
export const WakeLockButton: React.FC = () => {
|
|
955
|
+
const { enabled, requestWakeLock, releaseWakeLock } = useWakeLock({
|
|
956
|
+
enableOnLoad: false,
|
|
957
|
+
});
|
|
958
|
+
|
|
959
|
+
return (
|
|
960
|
+
<>
|
|
961
|
+
<h1>Wakelock enabled: {enabled.toString()}</h1>
|
|
962
|
+
<button onClick={requestWakeLock}>Enable wakelock</button>
|
|
963
|
+
<button onClick={releaseWakeLock}>Disable wakelock</button>
|
|
964
|
+
</>
|
|
965
|
+
);
|
|
966
|
+
};
|
|
967
|
+
```
|
|
968
|
+
|
|
969
|
+
---
|
|
970
|
+
|
|
971
|
+
###### Handling Wake Lock errors
|
|
972
|
+
|
|
973
|
+
```tsx
|
|
974
|
+
import {
|
|
975
|
+
useWakeLock,
|
|
976
|
+
type OnWakeLockRequestError,
|
|
977
|
+
} from "@alessiofrittoli/react-hooks";
|
|
978
|
+
|
|
979
|
+
const onError: OnWakeLockRequestError = (error) => {
|
|
980
|
+
alert("Could not enable Wake Lock: " + error.message);
|
|
981
|
+
};
|
|
982
|
+
|
|
983
|
+
export const WakeLockWithError: React.FC = () => {
|
|
984
|
+
const { enabled, requestWakeLock } = useWakeLock({ onError });
|
|
985
|
+
|
|
986
|
+
return (
|
|
987
|
+
<button onClick={requestWakeLock}>
|
|
988
|
+
{enabled ? "Wake Lock enabled" : "Enable Wake Lock"}
|
|
989
|
+
</button>
|
|
990
|
+
);
|
|
991
|
+
};
|
|
800
992
|
```
|
|
801
993
|
|
|
802
994
|
</details>
|
|
@@ -815,10 +1007,10 @@ This comes pretty handy when rendering a modal that shouldn't be closed without
|
|
|
815
1007
|
|
|
816
1008
|
<summary style="cursor:pointer">Parameters</summary>
|
|
817
1009
|
|
|
818
|
-
| Parameter | Type
|
|
819
|
-
|
|
820
|
-
| `target` | `React.RefObject<HTMLElement\|null>` | The target HTMLElement React RefObject to trap focus within.
|
|
821
|
-
| |
|
|
1010
|
+
| Parameter | Type | Description |
|
|
1011
|
+
| --------- | ------------------------------------ | ------------------------------------------------------------------------------------------- |
|
|
1012
|
+
| `target` | `React.RefObject<HTMLElement\|null>` | The target HTMLElement React RefObject to trap focus within. |
|
|
1013
|
+
| | | If no target is given, you must provide the target HTMLElement when calling `setFocusTrap`. |
|
|
822
1014
|
|
|
823
1015
|
</details>
|
|
824
1016
|
|
|
@@ -846,22 +1038,22 @@ A tuple containing:
|
|
|
846
1038
|
###### Defining the target on hook initialization
|
|
847
1039
|
|
|
848
1040
|
```tsx
|
|
849
|
-
import { useFocusTrap } from
|
|
1041
|
+
import { useFocusTrap } from "@alessiofrittoli/react-hooks";
|
|
850
1042
|
|
|
851
|
-
const modalRef = useRef<HTMLDivElement>(
|
|
852
|
-
const [
|
|
1043
|
+
const modalRef = useRef<HTMLDivElement>(null);
|
|
1044
|
+
const [setFocusTrap, restoreFocusTrap] = useFocusTrap(modalRef);
|
|
853
1045
|
|
|
854
|
-
const modalOpenHandler = useCallback(
|
|
855
|
-
if (
|
|
1046
|
+
const modalOpenHandler = useCallback(() => {
|
|
1047
|
+
if (!modalRef.current) return;
|
|
856
1048
|
// ... open modal
|
|
857
|
-
setFocusTrap()
|
|
858
|
-
modalRef.current.focus() // focus the dialog so next tab will focus the next element inside the modal
|
|
859
|
-
}, [
|
|
1049
|
+
setFocusTrap();
|
|
1050
|
+
modalRef.current.focus(); // focus the dialog so next tab will focus the next element inside the modal
|
|
1051
|
+
}, [setFocusTrap]);
|
|
860
1052
|
|
|
861
|
-
const modalCloseHandler = useCallback(
|
|
1053
|
+
const modalCloseHandler = useCallback(() => {
|
|
862
1054
|
// ... close modal
|
|
863
|
-
restoreFocusTrap() // cancel focus trap and restore focus to the last active element before enablig the focus trap
|
|
864
|
-
}, [
|
|
1055
|
+
restoreFocusTrap(); // cancel focus trap and restore focus to the last active element before enablig the focus trap
|
|
1056
|
+
}, [restoreFocusTrap]);
|
|
865
1057
|
```
|
|
866
1058
|
|
|
867
1059
|
---
|
|
@@ -869,25 +1061,25 @@ const modalCloseHandler = useCallback( () => {
|
|
|
869
1061
|
###### Defining the target ondemand
|
|
870
1062
|
|
|
871
1063
|
```tsx
|
|
872
|
-
import { useFocusTrap } from
|
|
1064
|
+
import { useFocusTrap } from "@alessiofrittoli/react-hooks";
|
|
873
1065
|
|
|
874
|
-
const modalRef = useRef<HTMLDivElement>(
|
|
875
|
-
const modal2Ref = useRef<HTMLDivElement>(
|
|
876
|
-
const [
|
|
1066
|
+
const modalRef = useRef<HTMLDivElement>(null);
|
|
1067
|
+
const modal2Ref = useRef<HTMLDivElement>(null);
|
|
1068
|
+
const [setFocusTrap, restoreFocusTrap] = useFocusTrap();
|
|
877
1069
|
|
|
878
|
-
const modalOpenHandler = useCallback(
|
|
879
|
-
if (
|
|
1070
|
+
const modalOpenHandler = useCallback(() => {
|
|
1071
|
+
if (!modalRef.current) return;
|
|
880
1072
|
// ... open modal
|
|
881
|
-
setFocusTrap(
|
|
882
|
-
modalRef.current.focus()
|
|
883
|
-
}, [
|
|
1073
|
+
setFocusTrap(modalRef.current);
|
|
1074
|
+
modalRef.current.focus();
|
|
1075
|
+
}, [setFocusTrap]);
|
|
884
1076
|
|
|
885
|
-
const modal2OpenHandler = useCallback(
|
|
886
|
-
if (
|
|
1077
|
+
const modal2OpenHandler = useCallback(() => {
|
|
1078
|
+
if (!modal2Ref.current) return;
|
|
887
1079
|
// ... open modal
|
|
888
|
-
setFocusTrap(
|
|
889
|
-
modal2Ref.current.focus()
|
|
890
|
-
}, [
|
|
1080
|
+
setFocusTrap(modal2Ref.current);
|
|
1081
|
+
modal2Ref.current.focus();
|
|
1082
|
+
}, [setFocusTrap]);
|
|
891
1083
|
```
|
|
892
1084
|
|
|
893
1085
|
</details>
|
|
@@ -902,33 +1094,33 @@ Check if the given target Element is intersecting with an ancestor Element or wi
|
|
|
902
1094
|
|
|
903
1095
|
<summary style="cursor:pointer">Parameters</summary>
|
|
904
1096
|
|
|
905
|
-
| Parameter
|
|
906
|
-
|
|
907
|
-
| `target`
|
|
908
|
-
| `options`
|
|
909
|
-
| `options.root`
|
|
910
|
-
| `options.margin`
|
|
911
|
-
| `options.amount`
|
|
912
|
-
|
|
|
913
|
-
|
|
|
914
|
-
|
|
|
915
|
-
|
|
|
916
|
-
|
|
|
917
|
-
| `options.once`
|
|
918
|
-
| `options.initial`
|
|
919
|
-
| `options.enable`
|
|
920
|
-
| `options.onIntersect` | `OnIntersectStateHandler`
|
|
921
|
-
|
|
|
922
|
-
|
|
|
923
|
-
|
|
|
924
|
-
| `options.onEnter`
|
|
925
|
-
|
|
|
926
|
-
|
|
|
927
|
-
|
|
|
928
|
-
| `options.onExit`
|
|
929
|
-
|
|
|
930
|
-
|
|
|
931
|
-
|
|
|
1097
|
+
| Parameter | Type | Description |
|
|
1098
|
+
| --------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1099
|
+
| `target` | `React.RefObject<Element\|null>` | The React.RefObject of the target Element to observe. |
|
|
1100
|
+
| `options` | `UseInViewOptions` | (Optional) An object defining custom `IntersectionObserver` options. |
|
|
1101
|
+
| `options.root` | `Element\|Document\|false\|null` | (Optional) Identifies the `Element` or `Document` whose bounds are treated as the bounding box of the viewport for the Element which is the observer's target. |
|
|
1102
|
+
| `options.margin` | `MarginType` | (Optional) A string, formatted similarly to the CSS margin property's value, which contains offsets for one or more sides of the root's bounding box. |
|
|
1103
|
+
| `options.amount` | `'all'\|'some'\|number\|number[]` | (Optional) The intersecting target thresholds. |
|
|
1104
|
+
| | | Threshold can be set to: |
|
|
1105
|
+
| | | - `all` - `1` will be used. |
|
|
1106
|
+
| | | - `some` - `0.5` will be used. |
|
|
1107
|
+
| | | - `number` |
|
|
1108
|
+
| | | - `number[]` |
|
|
1109
|
+
| `options.once` | `boolean` | (Optional) By setting this to `true` the observer will be disconnected after the target Element enters the viewport. |
|
|
1110
|
+
| `options.initial` | `boolean` | (Optional) Initial value. This value is used while server rendering then will be updated in the client based on target visibility. Default: `false`. |
|
|
1111
|
+
| `options.enable` | `boolean` | (Optional) Defines the initial observation activity. Use the returned `setEnabled` to update this state. Default: `true`. |
|
|
1112
|
+
| `options.onIntersect` | `OnIntersectStateHandler` | (Optional) A custom callback executed when target element's visibility has crossed one or more thresholds. |
|
|
1113
|
+
| | | This callback is awaited before any state update. |
|
|
1114
|
+
| | | If an error is thrown the React State update won't be fired. |
|
|
1115
|
+
| | | ⚠️ Wrap your callback with `useCallback` to avoid unnecessary `IntersectionObserver` recreation. |
|
|
1116
|
+
| `options.onEnter` | `OnIntersectHandler` | (Optional) A custom callback executed when target element's visibility has crossed one or more thresholds. |
|
|
1117
|
+
| | | This callback is awaited before any state update. |
|
|
1118
|
+
| | | If an error is thrown the React State update won't be fired. |
|
|
1119
|
+
| | | ⚠️ Wrap your callback with `useCallback` to avoid unnecessary `IntersectionObserver` recreation. |
|
|
1120
|
+
| `options.onExit` | `OnIntersectHandler` | (Optional) A custom callback executed when target element's visibility has crossed one or more thresholds. |
|
|
1121
|
+
| | | This callback is awaited before any state update. |
|
|
1122
|
+
| | | If an error is thrown the React State update won't be fired. |
|
|
1123
|
+
| | | ⚠️ Wrap your callback with `useCallback` to avoid unnecessary `IntersectionObserver` recreation. |
|
|
932
1124
|
|
|
933
1125
|
</details>
|
|
934
1126
|
|
|
@@ -959,46 +1151,44 @@ An object containing:
|
|
|
959
1151
|
###### Basic usage
|
|
960
1152
|
|
|
961
1153
|
```tsx
|
|
962
|
-
|
|
1154
|
+
"use client";
|
|
963
1155
|
|
|
964
|
-
import { useRef } from
|
|
965
|
-
import { useInView } from
|
|
1156
|
+
import { useRef } from "react";
|
|
1157
|
+
import { useInView } from "@alessiofrittoli/react-hooks";
|
|
966
1158
|
|
|
967
1159
|
const UseInViewExample: React.FC = () => {
|
|
1160
|
+
const targetRef = useRef<HTMLDivElement>(null);
|
|
1161
|
+
const { inView } = useInView(ref);
|
|
968
1162
|
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
1163
|
+
return Array.from(Array(6)).map((value, index) => (
|
|
1164
|
+
<div
|
|
1165
|
+
key={index}
|
|
1166
|
+
style={{
|
|
1167
|
+
height: "50vh",
|
|
1168
|
+
border: "1px solid red",
|
|
1169
|
+
display: "flex",
|
|
1170
|
+
alignItems: "center",
|
|
1171
|
+
justifyContent: "center",
|
|
1172
|
+
}}
|
|
1173
|
+
>
|
|
974
1174
|
<div
|
|
975
|
-
|
|
976
|
-
style={
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
1175
|
+
ref={index === 2 ? targetRef : undefined}
|
|
1176
|
+
style={{
|
|
1177
|
+
width: 150,
|
|
1178
|
+
height: 150,
|
|
1179
|
+
borderRadius: 12,
|
|
1180
|
+
display: "flex",
|
|
1181
|
+
alignItems: "center",
|
|
1182
|
+
justifyContent: "center",
|
|
1183
|
+
background: inView ? "#51AF83" : "#201A1B",
|
|
1184
|
+
color: inView ? "#201A1B" : "#FFFFFF",
|
|
1185
|
+
}}
|
|
983
1186
|
>
|
|
984
|
-
|
|
985
|
-
ref={ index === 2 ? targetRef : undefined }
|
|
986
|
-
style={ {
|
|
987
|
-
width : 150,
|
|
988
|
-
height : 150,
|
|
989
|
-
borderRadius : 12,
|
|
990
|
-
display : 'flex',
|
|
991
|
-
alignItems : 'center',
|
|
992
|
-
justifyContent : 'center',
|
|
993
|
-
background : inView ? '#51AF83' : '#201A1B',
|
|
994
|
-
color : inView ? '#201A1B' : '#FFFFFF',
|
|
995
|
-
} }
|
|
996
|
-
>{ index + 1 }</div>
|
|
1187
|
+
{index + 1}
|
|
997
1188
|
</div>
|
|
998
|
-
|
|
999
|
-
)
|
|
1000
|
-
|
|
1001
|
-
}
|
|
1189
|
+
</div>
|
|
1190
|
+
));
|
|
1191
|
+
};
|
|
1002
1192
|
```
|
|
1003
1193
|
|
|
1004
1194
|
---
|
|
@@ -1006,34 +1196,30 @@ const UseInViewExample: React.FC = () => {
|
|
|
1006
1196
|
###### Disconnect observer after target enters the viewport
|
|
1007
1197
|
|
|
1008
1198
|
```tsx
|
|
1009
|
-
|
|
1199
|
+
"use client";
|
|
1010
1200
|
|
|
1011
|
-
import { useRef } from
|
|
1012
|
-
import { useInView } from
|
|
1201
|
+
import { useRef } from "react";
|
|
1202
|
+
import { useInView } from "@alessiofrittoli/react-hooks";
|
|
1013
1203
|
|
|
1014
1204
|
const OnceExample: React.FC = () => {
|
|
1205
|
+
const targetRef = useRef<HTMLDivElement>(null);
|
|
1206
|
+
const { inView } = useInView(targetRef, { once: true });
|
|
1015
1207
|
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
if ( ! inView ) return
|
|
1022
|
-
console.count( 'Fired only once: element entered viewport.' )
|
|
1023
|
-
|
|
1024
|
-
}, [ inView ] )
|
|
1208
|
+
useEffect(() => {
|
|
1209
|
+
if (!inView) return;
|
|
1210
|
+
console.count("Fired only once: element entered viewport.");
|
|
1211
|
+
}, [inView]);
|
|
1025
1212
|
|
|
1026
1213
|
return (
|
|
1027
1214
|
<div
|
|
1028
|
-
ref={
|
|
1029
|
-
style={
|
|
1030
|
-
height
|
|
1031
|
-
background
|
|
1032
|
-
}
|
|
1215
|
+
ref={targetRef}
|
|
1216
|
+
style={{
|
|
1217
|
+
height: 200,
|
|
1218
|
+
background: inView ? "lime" : "gray",
|
|
1219
|
+
}}
|
|
1033
1220
|
/>
|
|
1034
|
-
)
|
|
1035
|
-
|
|
1036
|
-
}
|
|
1221
|
+
);
|
|
1222
|
+
};
|
|
1037
1223
|
```
|
|
1038
1224
|
|
|
1039
1225
|
---
|
|
@@ -1041,35 +1227,33 @@ const OnceExample: React.FC = () => {
|
|
|
1041
1227
|
###### Observe target only when needed
|
|
1042
1228
|
|
|
1043
1229
|
```tsx
|
|
1044
|
-
|
|
1230
|
+
"use client";
|
|
1045
1231
|
|
|
1046
|
-
import { useRef } from
|
|
1047
|
-
import { useInView } from
|
|
1232
|
+
import { useRef } from "react";
|
|
1233
|
+
import { useInView } from "@alessiofrittoli/react-hooks";
|
|
1048
1234
|
|
|
1049
1235
|
const OnDemandObservation: React.FC = () => {
|
|
1050
|
-
|
|
1051
|
-
const
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
} = useInView( targetRef, { enable: false } )
|
|
1236
|
+
const targetRef = useRef<HTMLDivElement>(null);
|
|
1237
|
+
const { inView, enabled, setEnabled } = useInView(targetRef, {
|
|
1238
|
+
enable: false,
|
|
1239
|
+
});
|
|
1055
1240
|
|
|
1056
1241
|
return (
|
|
1057
1242
|
<div>
|
|
1058
|
-
<button onClick={
|
|
1059
|
-
{
|
|
1243
|
+
<button onClick={() => setEnabled((prev) => !prev)}>
|
|
1244
|
+
{enabled ? "Disconnect observer" : "Observe"}
|
|
1060
1245
|
</button>
|
|
1061
1246
|
<div
|
|
1062
|
-
ref={
|
|
1063
|
-
style={
|
|
1064
|
-
height
|
|
1065
|
-
marginTop
|
|
1066
|
-
background
|
|
1067
|
-
}
|
|
1247
|
+
ref={targetRef}
|
|
1248
|
+
style={{
|
|
1249
|
+
height: 200,
|
|
1250
|
+
marginTop: 50,
|
|
1251
|
+
background: inView ? "lime" : "gray",
|
|
1252
|
+
}}
|
|
1068
1253
|
/>
|
|
1069
1254
|
</div>
|
|
1070
|
-
)
|
|
1071
|
-
|
|
1072
|
-
}
|
|
1255
|
+
);
|
|
1256
|
+
};
|
|
1073
1257
|
```
|
|
1074
1258
|
|
|
1075
1259
|
---
|
|
@@ -1077,42 +1261,44 @@ const OnDemandObservation: React.FC = () => {
|
|
|
1077
1261
|
###### Execute custom callback when intersection occurs
|
|
1078
1262
|
|
|
1079
1263
|
```tsx
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
import { useRef } from 'react'
|
|
1083
|
-
import { useInView, type OnIntersectStateHandler } from '@alessiofrittoli/react-hooks'
|
|
1264
|
+
"use client";
|
|
1084
1265
|
|
|
1266
|
+
import { useRef } from "react";
|
|
1267
|
+
import {
|
|
1268
|
+
useInView,
|
|
1269
|
+
type OnIntersectStateHandler,
|
|
1270
|
+
} from "@alessiofrittoli/react-hooks";
|
|
1085
1271
|
|
|
1086
1272
|
const AsyncStartExample: React.FC = () => {
|
|
1273
|
+
const targetRef = useRef<HTMLDivElement>(null);
|
|
1274
|
+
const onIntersect = useCallback<OnIntersectStateHandler>(
|
|
1275
|
+
async ({ entry, isEntering }) => {
|
|
1276
|
+
if (isEntering) {
|
|
1277
|
+
console.log("Delaying state update...");
|
|
1278
|
+
await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulate delay
|
|
1279
|
+
console.log("Async task completed. `inView` will now be updated.");
|
|
1280
|
+
return;
|
|
1281
|
+
}
|
|
1087
1282
|
|
|
1088
|
-
|
|
1089
|
-
|
|
1283
|
+
console.log("Delaying state update...");
|
|
1284
|
+
await new Promise((resolve) => setTimeout(resolve, 1000)); // Simulate delay
|
|
1285
|
+
console.log("Async task completed. `inView` will now be updated.");
|
|
1286
|
+
},
|
|
1287
|
+
[]
|
|
1288
|
+
);
|
|
1090
1289
|
|
|
1091
|
-
|
|
1092
|
-
console.log( 'Delaying state update...' )
|
|
1093
|
-
await new Promise( resolve => setTimeout( resolve, 1000 ) ) // Simulate delay
|
|
1094
|
-
console.log( 'Async task completed. `inView` will now be updated.' )
|
|
1095
|
-
return
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
console.log( 'Delaying state update...' )
|
|
1099
|
-
await new Promise( resolve => setTimeout( resolve, 1000 ) ) // Simulate delay
|
|
1100
|
-
console.log( 'Async task completed. `inView` will now be updated.' )
|
|
1101
|
-
|
|
1102
|
-
}, [] )
|
|
1103
|
-
|
|
1104
|
-
const { inView } = useInView( targetRef, { onIntersect } )
|
|
1290
|
+
const { inView } = useInView(targetRef, { onIntersect });
|
|
1105
1291
|
|
|
1106
1292
|
return (
|
|
1107
1293
|
<div
|
|
1108
|
-
ref={
|
|
1109
|
-
style={
|
|
1110
|
-
height
|
|
1111
|
-
background
|
|
1112
|
-
}
|
|
1294
|
+
ref={targetRef}
|
|
1295
|
+
style={{
|
|
1296
|
+
height: 200,
|
|
1297
|
+
background: inView ? "lime" : "gray",
|
|
1298
|
+
}}
|
|
1113
1299
|
/>
|
|
1114
|
-
)
|
|
1115
|
-
}
|
|
1300
|
+
);
|
|
1301
|
+
};
|
|
1116
1302
|
```
|
|
1117
1303
|
|
|
1118
1304
|
---
|
|
@@ -1120,34 +1306,35 @@ const AsyncStartExample: React.FC = () => {
|
|
|
1120
1306
|
###### Execute custom callback when `onEnter` and `onExit`
|
|
1121
1307
|
|
|
1122
1308
|
```tsx
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
import { useRef } from 'react'
|
|
1126
|
-
import { useInView, type OnIntersectHandler } from '@alessiofrittoli/react-hooks'
|
|
1309
|
+
"use client";
|
|
1127
1310
|
|
|
1311
|
+
import { useRef } from "react";
|
|
1312
|
+
import {
|
|
1313
|
+
useInView,
|
|
1314
|
+
type OnIntersectHandler,
|
|
1315
|
+
} from "@alessiofrittoli/react-hooks";
|
|
1128
1316
|
|
|
1129
1317
|
const AsyncStartExample: React.FC = () => {
|
|
1318
|
+
const targetRef = useRef<HTMLDivElement>(null);
|
|
1319
|
+
const onEnter = useCallback<OnIntersectHandler>(async ({ entry }) => {
|
|
1320
|
+
console.log("In viewport - ", entry);
|
|
1321
|
+
}, []);
|
|
1322
|
+
const onExit = useCallback<OnIntersectHandler>(async ({ entry }) => {
|
|
1323
|
+
console.log("Exited viewport - ", entry);
|
|
1324
|
+
}, []);
|
|
1130
1325
|
|
|
1131
|
-
const
|
|
1132
|
-
const onEnter = useCallback<OnIntersectHandler>( async ( { entry } ) => {
|
|
1133
|
-
console.log( 'In viewport - ', entry )
|
|
1134
|
-
}, [] )
|
|
1135
|
-
const onExit = useCallback<OnIntersectHandler>( async ( { entry } ) => {
|
|
1136
|
-
console.log( 'Exited viewport - ', entry )
|
|
1137
|
-
}, [] )
|
|
1138
|
-
|
|
1139
|
-
const { inView } = useInView( targetRef, { onEnter, onExit } )
|
|
1326
|
+
const { inView } = useInView(targetRef, { onEnter, onExit });
|
|
1140
1327
|
|
|
1141
1328
|
return (
|
|
1142
1329
|
<div
|
|
1143
|
-
ref={
|
|
1144
|
-
style={
|
|
1145
|
-
height
|
|
1146
|
-
background
|
|
1147
|
-
}
|
|
1330
|
+
ref={targetRef}
|
|
1331
|
+
style={{
|
|
1332
|
+
height: 200,
|
|
1333
|
+
background: inView ? "lime" : "gray",
|
|
1334
|
+
}}
|
|
1148
1335
|
/>
|
|
1149
|
-
)
|
|
1150
|
-
}
|
|
1336
|
+
);
|
|
1337
|
+
};
|
|
1151
1338
|
```
|
|
1152
1339
|
|
|
1153
1340
|
</details>
|
|
@@ -1162,8 +1349,8 @@ Prevent Element overflow.
|
|
|
1162
1349
|
|
|
1163
1350
|
<summary style="cursor:pointer">Parameters</summary>
|
|
1164
1351
|
|
|
1165
|
-
| Parameter | Type
|
|
1166
|
-
|
|
1352
|
+
| Parameter | Type | Default | Description |
|
|
1353
|
+
| --------- | ------------------------------------ | -------------------------- | -------------------------------------------------- |
|
|
1167
1354
|
| `target` | `React.RefObject<HTMLElement\|null>` | `Document.documentElement` | (Optional) The React RefObject target HTMLElement. |
|
|
1168
1355
|
|
|
1169
1356
|
</details>
|
|
@@ -1243,7 +1430,7 @@ Handle input states with ease.
|
|
|
1243
1430
|
<summary style="cursor:pointer">Type Parameters</summary>
|
|
1244
1431
|
|
|
1245
1432
|
| Parameter | Description |
|
|
1246
|
-
|
|
1433
|
+
| --------- | ---------------------- |
|
|
1247
1434
|
| `I` | The input value type. |
|
|
1248
1435
|
| `O` | The output value type. |
|
|
1249
1436
|
|
|
@@ -1255,15 +1442,15 @@ Handle input states with ease.
|
|
|
1255
1442
|
|
|
1256
1443
|
<summary style="cursor:pointer">Parameters</summary>
|
|
1257
1444
|
|
|
1258
|
-
| Parameter
|
|
1259
|
-
|
|
1260
|
-
| `options`
|
|
1261
|
-
| `options.inputRef`
|
|
1262
|
-
| `options.initialValue` | `O\|null`
|
|
1263
|
-
| `options.touchTimeout` | `number`
|
|
1264
|
-
| `options.validate`
|
|
1265
|
-
| `options.parse`
|
|
1266
|
-
| `options.onChange`
|
|
1445
|
+
| Parameter | Type | Default | Description |
|
|
1446
|
+
| ---------------------- | ---------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1447
|
+
| `options` | `UseInputOptions<I, O>` | `{}` | An object defining custom options. |
|
|
1448
|
+
| `options.inputRef` | `React.RefObject<InputType>` | - | (Optional) The React HTML input element ref. |
|
|
1449
|
+
| `options.initialValue` | `O\|null` | - | (Optional) The input initial value. |
|
|
1450
|
+
| `options.touchTimeout` | `number` | 600 | (Optional) A timeout in milliseconds which will be used to define the input as "touched" thus validations are triggered and errors can be displayed. |
|
|
1451
|
+
| `options.validate` | `ValidateValueHandler<O>` | - | (Optional) Value validation handler. If `parse` callback is given, the `value` will be parsed before validation. |
|
|
1452
|
+
| `options.parse` | `ParseValueHandler<I, O>` | - | (Optional) Parse value. |
|
|
1453
|
+
| `options.onChange` | `ChangeHandler<O>` | - | (Optional) A callable function executed when the `ChangeEvent` is dispatched on the HTML input element. |
|
|
1267
1454
|
|
|
1268
1455
|
</details>
|
|
1269
1456
|
|
|
@@ -1277,18 +1464,18 @@ Type: `UseInputOutput<I, O>`
|
|
|
1277
1464
|
|
|
1278
1465
|
An object containing the following properties:
|
|
1279
1466
|
|
|
1280
|
-
| Property | Type
|
|
1281
|
-
|
|
1282
|
-
| `isEmpty` | `boolean`
|
|
1283
|
-
| `hasError` | `boolean`
|
|
1284
|
-
|
|
|
1285
|
-
|
|
|
1286
|
-
| `changeHandler` | `React.ChangeEventHandler<InputType>` | Change handler callback used to handle Input change events.
|
|
1287
|
-
| `blurHandler` | `() => void`
|
|
1288
|
-
| `setValue` | `( value: O ) => void`
|
|
1289
|
-
| `submit` | `() => void`
|
|
1290
|
-
| `reset` | `() => void`
|
|
1291
|
-
| `focus` | `() => void`
|
|
1467
|
+
| Property | Type | Description |
|
|
1468
|
+
| --------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
1469
|
+
| `isEmpty` | `boolean` | Indicates whether the Input is empty or not. |
|
|
1470
|
+
| `hasError` | `boolean` | Indicates whether the input has error or not. |
|
|
1471
|
+
| | | It will return true if the Input does not pass the validation checks and it has been touched. |
|
|
1472
|
+
| | | Please refer to the `isValid` property to check the Input validity regardless of whether it has been touched or not. |
|
|
1473
|
+
| `changeHandler` | `React.ChangeEventHandler<InputType>` | Change handler callback used to handle Input change events. |
|
|
1474
|
+
| `blurHandler` | `() => void` | Blur handler callback used to handle Input blur events. |
|
|
1475
|
+
| `setValue` | `( value: O ) => void` | Call `setValue` method to update input value. |
|
|
1476
|
+
| `submit` | `() => void` | Call `submit` method to re-run validations and ensure error state is updated successfully. |
|
|
1477
|
+
| `reset` | `() => void` | Call `reset` method to reset the Input state. |
|
|
1478
|
+
| `focus` | `() => void` | Call `focus` method to focus the Input Element. `inputRef` must be provided in the input options. |
|
|
1292
1479
|
|
|
1293
1480
|
</details>
|
|
1294
1481
|
|
|
@@ -1302,19 +1489,17 @@ An object containing the following properties:
|
|
|
1302
1489
|
|
|
1303
1490
|
```tsx
|
|
1304
1491
|
const MyComponent: React.FC = () => {
|
|
1305
|
-
|
|
1306
|
-
const input = useInput<string>()
|
|
1492
|
+
const input = useInput<string>();
|
|
1307
1493
|
|
|
1308
1494
|
return (
|
|
1309
1495
|
<input
|
|
1310
|
-
type=
|
|
1311
|
-
value={
|
|
1312
|
-
onChange={
|
|
1313
|
-
onBlur={
|
|
1496
|
+
type="text"
|
|
1497
|
+
value={input.value || ""}
|
|
1498
|
+
onChange={input.changeHandler}
|
|
1499
|
+
onBlur={input.blurHandler}
|
|
1314
1500
|
/>
|
|
1315
|
-
)
|
|
1316
|
-
|
|
1317
|
-
}
|
|
1501
|
+
);
|
|
1502
|
+
};
|
|
1318
1503
|
```
|
|
1319
1504
|
|
|
1320
1505
|
---
|
|
@@ -1322,32 +1507,30 @@ const MyComponent: React.FC = () => {
|
|
|
1322
1507
|
###### Displaying custom error messages
|
|
1323
1508
|
|
|
1324
1509
|
```tsx
|
|
1325
|
-
import {
|
|
1510
|
+
import {
|
|
1511
|
+
useInput,
|
|
1512
|
+
type ValidateValueHandler,
|
|
1513
|
+
} from "@alessiofrittoli/react-hooks";
|
|
1326
1514
|
|
|
1327
|
-
const isNotEmpty: ValidateValueHandler<string> = value =>
|
|
1328
|
-
!
|
|
1329
|
-
)
|
|
1515
|
+
const isNotEmpty: ValidateValueHandler<string> = (value) =>
|
|
1516
|
+
!value ? false : value.trim().length > 0;
|
|
1330
1517
|
|
|
1331
1518
|
const MyComponent: React.FC = () => {
|
|
1332
|
-
|
|
1333
|
-
const input = useInput<string>( {
|
|
1519
|
+
const input = useInput<string>({
|
|
1334
1520
|
validate: isNotEmpty,
|
|
1335
|
-
}
|
|
1521
|
+
});
|
|
1336
1522
|
|
|
1337
1523
|
return (
|
|
1338
1524
|
<>
|
|
1339
1525
|
<input
|
|
1340
|
-
value={
|
|
1341
|
-
onChange={
|
|
1342
|
-
onBlur={
|
|
1526
|
+
value={input.value || ""}
|
|
1527
|
+
onChange={input.changeHandler}
|
|
1528
|
+
onBlur={input.blurHandler}
|
|
1343
1529
|
/>
|
|
1344
|
-
{
|
|
1345
|
-
<span>The input cannot be empty.</span>
|
|
1346
|
-
) }
|
|
1530
|
+
{input.hasError && <span>The input cannot be empty.</span>}
|
|
1347
1531
|
</>
|
|
1348
|
-
)
|
|
1349
|
-
|
|
1350
|
-
}
|
|
1532
|
+
);
|
|
1533
|
+
};
|
|
1351
1534
|
```
|
|
1352
1535
|
|
|
1353
1536
|
---
|
|
@@ -1355,42 +1538,39 @@ const MyComponent: React.FC = () => {
|
|
|
1355
1538
|
###### Parsing and validating parsed value
|
|
1356
1539
|
|
|
1357
1540
|
```tsx
|
|
1358
|
-
import { formatDate, isValidDate } from
|
|
1359
|
-
import {
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1541
|
+
import { formatDate, isValidDate } from "@alessiofrittoli/date-utils";
|
|
1542
|
+
import {
|
|
1543
|
+
useInput,
|
|
1544
|
+
type ValidateValueHandler,
|
|
1545
|
+
type ParseValueHandler,
|
|
1546
|
+
} from "@alessiofrittoli/react-hooks";
|
|
1365
1547
|
|
|
1366
|
-
const
|
|
1367
|
-
|
|
1368
|
-
)
|
|
1548
|
+
const parseStringToDate: ParseValueHandler<string, Date> = (value) =>
|
|
1549
|
+
value ? new Date(value) : undefined;
|
|
1369
1550
|
|
|
1551
|
+
const validateInputDate: ValidateValueHandler<Date> = (value) =>
|
|
1552
|
+
isValidDate(value) && value.getTime() > Date.now();
|
|
1370
1553
|
|
|
1371
1554
|
const MyComponent: React.FC = () => {
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
} )
|
|
1377
|
-
|
|
1555
|
+
const input = useInput<string, Date>({
|
|
1556
|
+
parse: parseStringToDate,
|
|
1557
|
+
validate: validateInputDate,
|
|
1558
|
+
});
|
|
1378
1559
|
|
|
1379
1560
|
return (
|
|
1380
1561
|
<>
|
|
1381
1562
|
<input
|
|
1382
|
-
type=
|
|
1383
|
-
value={
|
|
1384
|
-
onChange={
|
|
1385
|
-
onBlur={
|
|
1563
|
+
type="datetime-local"
|
|
1564
|
+
value={input.value ? formatDate(input.value, "Y-m-dTH:i") : ""}
|
|
1565
|
+
onChange={input.changeHandler}
|
|
1566
|
+
onBlur={input.blurHandler}
|
|
1386
1567
|
/>
|
|
1387
|
-
{
|
|
1568
|
+
{input.hasError && (
|
|
1388
1569
|
<span>Please choose a date no earlier than today</span>
|
|
1389
|
-
)
|
|
1570
|
+
)}
|
|
1390
1571
|
</>
|
|
1391
|
-
)
|
|
1392
|
-
|
|
1393
|
-
}
|
|
1572
|
+
);
|
|
1573
|
+
};
|
|
1394
1574
|
```
|
|
1395
1575
|
|
|
1396
1576
|
</details>
|
|
@@ -1410,10 +1590,10 @@ Take a look at [`deferTask`](https://npmjs.com/package/@alessiofrittoli/web-util
|
|
|
1410
1590
|
|
|
1411
1591
|
<summary style="cursor:pointer">Type Parameters</summary>
|
|
1412
1592
|
|
|
1413
|
-
| Parameter | Description
|
|
1414
|
-
|
|
1593
|
+
| Parameter | Description |
|
|
1594
|
+
| --------- | ------------------------------------------------------------------------------------------------- |
|
|
1415
1595
|
| `T` | The task function definition. `unknown` types will be inherited by your function type definition. |
|
|
1416
|
-
| `U` | The task function arguments. `unknown` types will be inherited by your function type.
|
|
1596
|
+
| `U` | The task function arguments. `unknown` types will be inherited by your function type. |
|
|
1417
1597
|
|
|
1418
1598
|
</details>
|
|
1419
1599
|
|
|
@@ -1423,9 +1603,9 @@ Take a look at [`deferTask`](https://npmjs.com/package/@alessiofrittoli/web-util
|
|
|
1423
1603
|
|
|
1424
1604
|
<summary style="cursor:pointer">Parameters</summary>
|
|
1425
1605
|
|
|
1426
|
-
| Parameter | Type
|
|
1427
|
-
|
|
1428
|
-
| `task` | `T`
|
|
1606
|
+
| Parameter | Type | Description |
|
|
1607
|
+
| --------- | ---- | --------------------------- |
|
|
1608
|
+
| `task` | `T` | The task callable function. |
|
|
1429
1609
|
|
|
1430
1610
|
</details>
|
|
1431
1611
|
|
|
@@ -1473,8 +1653,8 @@ Modified version of `useEffect` that only run once on intial load.
|
|
|
1473
1653
|
|
|
1474
1654
|
<summary style="cursor:pointer">Parameters</summary>
|
|
1475
1655
|
|
|
1476
|
-
| Parameter | Type | Description
|
|
1477
|
-
|
|
1656
|
+
| Parameter | Type | Description |
|
|
1657
|
+
| --------- | ---------------------- | ------------------------------------------------------- |
|
|
1478
1658
|
| `effect` | `React.EffectCallback` | Imperative function that can return a cleanup function. |
|
|
1479
1659
|
|
|
1480
1660
|
</details>
|
|
@@ -1486,34 +1666,30 @@ Modified version of `useEffect` that only run once on intial load.
|
|
|
1486
1666
|
<summary style="cursor:pointer">Usage</summary>
|
|
1487
1667
|
|
|
1488
1668
|
```tsx
|
|
1489
|
-
|
|
1669
|
+
"use client";
|
|
1490
1670
|
|
|
1491
|
-
import { useEffect, useState } from
|
|
1492
|
-
import { useEffectOnce } from
|
|
1671
|
+
import { useEffect, useState } from "react";
|
|
1672
|
+
import { useEffectOnce } from "@alessiofrittoli/react-hooks";
|
|
1493
1673
|
|
|
1494
1674
|
export const ClientComponent: React.FC = () => {
|
|
1675
|
+
const [count, setCount] = useState(0);
|
|
1495
1676
|
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
return () => clearInterval( intv )
|
|
1503
|
-
}, [] )
|
|
1677
|
+
useEffect(() => {
|
|
1678
|
+
const intv = setInterval(() => {
|
|
1679
|
+
setCount((prev) => prev + 1); // update state each 1s
|
|
1680
|
+
}, 1000);
|
|
1681
|
+
return () => clearInterval(intv);
|
|
1682
|
+
}, []);
|
|
1504
1683
|
|
|
1505
|
-
useEffectOnce(
|
|
1506
|
-
console.log(
|
|
1684
|
+
useEffectOnce(() => {
|
|
1685
|
+
console.log("Component did mount");
|
|
1507
1686
|
return () => {
|
|
1508
|
-
console.log(
|
|
1509
|
-
}
|
|
1510
|
-
}
|
|
1511
|
-
|
|
1512
|
-
return (
|
|
1513
|
-
<div>{ count }</div>
|
|
1514
|
-
)
|
|
1687
|
+
console.log("Component did unmount");
|
|
1688
|
+
};
|
|
1689
|
+
});
|
|
1515
1690
|
|
|
1516
|
-
}
|
|
1691
|
+
return <div>{count}</div>;
|
|
1692
|
+
};
|
|
1517
1693
|
```
|
|
1518
1694
|
|
|
1519
1695
|
</details>
|
|
@@ -1528,9 +1704,9 @@ Modified version of `useEffect` that skips the first render.
|
|
|
1528
1704
|
|
|
1529
1705
|
<summary style="cursor:pointer">Parameters</summary>
|
|
1530
1706
|
|
|
1531
|
-
| Parameter | Type | Description
|
|
1532
|
-
|
|
1533
|
-
| `effect` | `React.EffectCallback` | Imperative function that can return a cleanup function.
|
|
1707
|
+
| Parameter | Type | Description |
|
|
1708
|
+
| --------- | ---------------------- | ----------------------------------------------------------------------- |
|
|
1709
|
+
| `effect` | `React.EffectCallback` | Imperative function that can return a cleanup function. |
|
|
1534
1710
|
| `deps` | `React.DependencyList` | If present, effect will only activate if the values in the list change. |
|
|
1535
1711
|
|
|
1536
1712
|
</details>
|
|
@@ -1542,41 +1718,37 @@ Modified version of `useEffect` that skips the first render.
|
|
|
1542
1718
|
<summary style="cursor:pointer">Usage</summary>
|
|
1543
1719
|
|
|
1544
1720
|
```tsx
|
|
1545
|
-
|
|
1721
|
+
"use client";
|
|
1546
1722
|
|
|
1547
|
-
import { useEffect, useState } from
|
|
1548
|
-
import { useUpdateEffect } from
|
|
1723
|
+
import { useEffect, useState } from "react";
|
|
1724
|
+
import { useUpdateEffect } from "@alessiofrittoli/react-hooks";
|
|
1549
1725
|
|
|
1550
1726
|
export const ClientComponent: React.FC = () => {
|
|
1727
|
+
const [count, setCount] = useState(0);
|
|
1551
1728
|
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
return () => clearInterval( intv )
|
|
1559
|
-
}, [] )
|
|
1729
|
+
useEffect(() => {
|
|
1730
|
+
const intv = setInterval(() => {
|
|
1731
|
+
setCount((prev) => prev + 1);
|
|
1732
|
+
}, 1000);
|
|
1733
|
+
return () => clearInterval(intv);
|
|
1734
|
+
}, []);
|
|
1560
1735
|
|
|
1561
|
-
useEffect(
|
|
1562
|
-
console.log(
|
|
1736
|
+
useEffect(() => {
|
|
1737
|
+
console.log("useEffect", count); // starts from 0
|
|
1563
1738
|
return () => {
|
|
1564
|
-
console.log(
|
|
1565
|
-
}
|
|
1566
|
-
}, [
|
|
1739
|
+
console.log("useEffect - clean up", count); // starts from 0
|
|
1740
|
+
};
|
|
1741
|
+
}, [count]);
|
|
1567
1742
|
|
|
1568
|
-
useUpdateEffect(
|
|
1569
|
-
console.log(
|
|
1743
|
+
useUpdateEffect(() => {
|
|
1744
|
+
console.log("useUpdateEffect", count); // starts from 1
|
|
1570
1745
|
return () => {
|
|
1571
|
-
console.log(
|
|
1572
|
-
}
|
|
1573
|
-
}, [
|
|
1746
|
+
console.log("useUpdateEffect - clean up", count); // starts from 1
|
|
1747
|
+
};
|
|
1748
|
+
}, [count]);
|
|
1574
1749
|
|
|
1575
|
-
return
|
|
1576
|
-
|
|
1577
|
-
)
|
|
1578
|
-
|
|
1579
|
-
}
|
|
1750
|
+
return <div>{count}</div>;
|
|
1751
|
+
};
|
|
1580
1752
|
```
|
|
1581
1753
|
|
|
1582
1754
|
</details>
|
|
@@ -1607,19 +1779,15 @@ Type: `boolean`
|
|
|
1607
1779
|
<summary style="cursor:pointer">Usage</summary>
|
|
1608
1780
|
|
|
1609
1781
|
```tsx
|
|
1610
|
-
|
|
1782
|
+
"use client";
|
|
1611
1783
|
|
|
1612
|
-
import { useIsClient } from
|
|
1784
|
+
import { useIsClient } from "@alessiofrittoli/react-hooks";
|
|
1613
1785
|
|
|
1614
1786
|
export const ClientComponent: React.FC = () => {
|
|
1787
|
+
const isClient = useIsClient();
|
|
1615
1788
|
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
return (
|
|
1619
|
-
<div>Running { ! isClient ? 'server' : 'client' }-side</div>
|
|
1620
|
-
)
|
|
1621
|
-
|
|
1622
|
-
}
|
|
1789
|
+
return <div>Running {!isClient ? "server" : "client"}-side</div>;
|
|
1790
|
+
};
|
|
1623
1791
|
```
|
|
1624
1792
|
|
|
1625
1793
|
</details>
|
|
@@ -1650,31 +1818,29 @@ Note that if the React Hook/Component has no state updates, `useIsFirstRender` w
|
|
|
1650
1818
|
<summary style="cursor:pointer">Usage</summary>
|
|
1651
1819
|
|
|
1652
1820
|
```tsx
|
|
1653
|
-
|
|
1821
|
+
"use client";
|
|
1654
1822
|
|
|
1655
|
-
import { useIsFirstRender } from
|
|
1823
|
+
import { useIsFirstRender } from "@alessiofrittoli/react-hooks";
|
|
1656
1824
|
|
|
1657
1825
|
export const ClientComponent: React.FC = () => {
|
|
1826
|
+
const isFirstRender = useIsFirstRender();
|
|
1827
|
+
const [counter, setCounter] = useState(0);
|
|
1658
1828
|
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
}, 1000 )
|
|
1666
|
-
return () => clearInterval( intv )
|
|
1667
|
-
}, [] )
|
|
1829
|
+
useEffect(() => {
|
|
1830
|
+
const intv = setInterval(() => {
|
|
1831
|
+
setCounter((prev) => prev + 1);
|
|
1832
|
+
}, 1000);
|
|
1833
|
+
return () => clearInterval(intv);
|
|
1834
|
+
}, []);
|
|
1668
1835
|
|
|
1669
1836
|
return (
|
|
1670
1837
|
<div>
|
|
1671
|
-
{
|
|
1838
|
+
{isFirstRender ? "First render" : "Subsequent render"}
|
|
1672
1839
|
<hr />
|
|
1673
|
-
{
|
|
1840
|
+
{counter}
|
|
1674
1841
|
</div>
|
|
1675
|
-
)
|
|
1676
|
-
|
|
1677
|
-
}
|
|
1842
|
+
);
|
|
1843
|
+
};
|
|
1678
1844
|
```
|
|
1679
1845
|
|
|
1680
1846
|
</details>
|
|
@@ -1701,8 +1867,8 @@ Provides functionality for single and group selection, as well as resetting the
|
|
|
1701
1867
|
|
|
1702
1868
|
<summary style="cursor:pointer">Type Parameters</summary>
|
|
1703
1869
|
|
|
1704
|
-
| Parameter | Description
|
|
1705
|
-
|
|
1870
|
+
| Parameter | Description |
|
|
1871
|
+
| --------- | -------------------------------------- |
|
|
1706
1872
|
| `V` | The type of the values in the `array`. |
|
|
1707
1873
|
|
|
1708
1874
|
</details>
|
|
@@ -1713,10 +1879,10 @@ Provides functionality for single and group selection, as well as resetting the
|
|
|
1713
1879
|
|
|
1714
1880
|
<summary style="cursor:pointer">Parameters</summary>
|
|
1715
1881
|
|
|
1716
|
-
| Parameter | Type | Default | Description
|
|
1717
|
-
|
|
1718
|
-
| `array` | `V[]` | -
|
|
1719
|
-
| `initial` | `V[]` | []
|
|
1882
|
+
| Parameter | Type | Default | Description |
|
|
1883
|
+
| --------- | ----- | ------- | ------------------------------------------- |
|
|
1884
|
+
| `array` | `V[]` | - | The array of items to manage selection for. |
|
|
1885
|
+
| `initial` | `V[]` | [] | The initial selection state. |
|
|
1720
1886
|
|
|
1721
1887
|
</details>
|
|
1722
1888
|
|
|
@@ -1746,77 +1912,78 @@ An object containing the selection state and handlers.
|
|
|
1746
1912
|
<summary style="cursor:pointer">Usage</summary>
|
|
1747
1913
|
|
|
1748
1914
|
```tsx
|
|
1749
|
-
|
|
1915
|
+
"use client";
|
|
1750
1916
|
|
|
1751
|
-
import { useCallback, useMemo } from
|
|
1752
|
-
import { useSelection } from
|
|
1917
|
+
import { useCallback, useMemo } from "react";
|
|
1918
|
+
import { useSelection } from "@alessiofrittoli/react-hooks";
|
|
1753
1919
|
|
|
1754
|
-
interface Item
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
name : string
|
|
1920
|
+
interface Item {
|
|
1921
|
+
id: number;
|
|
1922
|
+
name: string;
|
|
1758
1923
|
}
|
|
1759
1924
|
|
|
1760
1925
|
const items: Item[] = [
|
|
1761
1926
|
{
|
|
1762
|
-
id
|
|
1763
|
-
name
|
|
1927
|
+
id: 1,
|
|
1928
|
+
name: "item-1",
|
|
1764
1929
|
},
|
|
1765
1930
|
{
|
|
1766
|
-
id
|
|
1767
|
-
name
|
|
1931
|
+
id: 2,
|
|
1932
|
+
name: "item-2",
|
|
1768
1933
|
},
|
|
1769
1934
|
{
|
|
1770
|
-
id
|
|
1771
|
-
name
|
|
1935
|
+
id: 3,
|
|
1936
|
+
name: "item-3",
|
|
1772
1937
|
},
|
|
1773
1938
|
{
|
|
1774
|
-
id
|
|
1775
|
-
name
|
|
1939
|
+
id: 4,
|
|
1940
|
+
name: "item-4",
|
|
1776
1941
|
},
|
|
1777
1942
|
{
|
|
1778
|
-
id
|
|
1779
|
-
name
|
|
1943
|
+
id: 5,
|
|
1944
|
+
name: "item-5",
|
|
1780
1945
|
},
|
|
1781
|
-
]
|
|
1782
|
-
|
|
1946
|
+
];
|
|
1783
1947
|
|
|
1784
1948
|
const MyComponent: React.FC = () => {
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
return groupSelect( id ) // group select
|
|
1949
|
+
const { setSelection, select, groupSelect, isSelected } = useSelection(
|
|
1950
|
+
useMemo(() => items.map((item) => item.id), [])
|
|
1951
|
+
);
|
|
1952
|
+
|
|
1953
|
+
const clickHandler = useCallback(
|
|
1954
|
+
(id: Item["id"]) => (event: React.MouseEvent<HTMLButtonElement>) => {
|
|
1955
|
+
if (event.shiftKey) {
|
|
1956
|
+
return groupSelect(id); // group select
|
|
1794
1957
|
}
|
|
1795
|
-
if (
|
|
1796
|
-
return select(
|
|
1958
|
+
if (event.metaKey || event.ctrlKey) {
|
|
1959
|
+
return select(id); // toggle single item in selection
|
|
1797
1960
|
}
|
|
1798
|
-
setSelection(
|
|
1799
|
-
prev.includes(
|
|
1800
|
-
)
|
|
1801
|
-
}
|
|
1802
|
-
|
|
1961
|
+
setSelection(
|
|
1962
|
+
(prev) => (prev.includes(id) ? [] : [id]) // toggle single item selection
|
|
1963
|
+
);
|
|
1964
|
+
},
|
|
1965
|
+
[select, groupSelect, setSelection]
|
|
1966
|
+
);
|
|
1803
1967
|
|
|
1804
1968
|
return (
|
|
1805
1969
|
<ul>
|
|
1806
|
-
{
|
|
1807
|
-
<li key={
|
|
1970
|
+
{items.map((item) => (
|
|
1971
|
+
<li key={item.id}>
|
|
1808
1972
|
<button
|
|
1809
|
-
onClick={
|
|
1810
|
-
style={
|
|
1811
|
-
border: isSelected(
|
|
1812
|
-
|
|
1813
|
-
|
|
1973
|
+
onClick={clickHandler(item.id)}
|
|
1974
|
+
style={{
|
|
1975
|
+
border: isSelected(item.id)
|
|
1976
|
+
? "1px solid red"
|
|
1977
|
+
: " 1px solid black",
|
|
1978
|
+
}}
|
|
1979
|
+
>
|
|
1980
|
+
{item.name}
|
|
1981
|
+
</button>
|
|
1814
1982
|
</li>
|
|
1815
|
-
)
|
|
1983
|
+
))}
|
|
1816
1984
|
</ul>
|
|
1817
|
-
)
|
|
1818
|
-
|
|
1819
|
-
}
|
|
1985
|
+
);
|
|
1986
|
+
};
|
|
1820
1987
|
```
|
|
1821
1988
|
|
|
1822
1989
|
</details>
|
|
@@ -1842,7 +2009,7 @@ The `Timeout` automatically restarts when the given `value` changes.
|
|
|
1842
2009
|
<summary style="cursor:pointer">Type Parameters</summary>
|
|
1843
2010
|
|
|
1844
2011
|
| Parameter | Description |
|
|
1845
|
-
|
|
2012
|
+
| --------- | ------------------------ |
|
|
1846
2013
|
| `T` | The type of the `value`. |
|
|
1847
2014
|
|
|
1848
2015
|
</details>
|
|
@@ -1853,10 +2020,10 @@ The `Timeout` automatically restarts when the given `value` changes.
|
|
|
1853
2020
|
|
|
1854
2021
|
<summary style="cursor:pointer">Parameters</summary>
|
|
1855
2022
|
|
|
1856
|
-
| Parameter | Type | Default | Description
|
|
1857
|
-
|
|
2023
|
+
| Parameter | Type | Default | Description |
|
|
2024
|
+
| --------- | -------- | ------- | ----------------------------------------------- |
|
|
1858
2025
|
| `value` | `T` | - | The value to debounce. This can be of any type. |
|
|
1859
|
-
| `delay` | `number` | 500 | The debounce delay in milliseconds.
|
|
2026
|
+
| `delay` | `number` | 500 | The debounce delay in milliseconds. |
|
|
1860
2027
|
|
|
1861
2028
|
</details>
|
|
1862
2029
|
|
|
@@ -1879,33 +2046,26 @@ The debounced value, which updates only after the delay has passed.
|
|
|
1879
2046
|
<summary style="cursor:pointer">Usage</summary>
|
|
1880
2047
|
|
|
1881
2048
|
```tsx
|
|
1882
|
-
|
|
2049
|
+
"use client";
|
|
1883
2050
|
|
|
1884
|
-
import { useEffect, useState } from
|
|
1885
|
-
import { useDebounce } from
|
|
2051
|
+
import { useEffect, useState } from "react";
|
|
2052
|
+
import { useDebounce } from "@alessiofrittoli/react-hooks";
|
|
1886
2053
|
|
|
1887
2054
|
const MyComponent: React.FC = () => {
|
|
2055
|
+
const [query, setQuery] = useState("");
|
|
2056
|
+
const debouncedQuery = useDebounce(query);
|
|
1888
2057
|
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
useEffect( () => {
|
|
1893
|
-
if ( ! debouncedQuery ) return
|
|
2058
|
+
useEffect(() => {
|
|
2059
|
+
if (!debouncedQuery) return;
|
|
1894
2060
|
|
|
1895
|
-
fetch(
|
|
2061
|
+
fetch("...", {
|
|
1896
2062
|
// ...
|
|
1897
|
-
body: JSON.stringify(
|
|
1898
|
-
}
|
|
1899
|
-
|
|
1900
|
-
}, [ debouncedQuery ] )
|
|
2063
|
+
body: JSON.stringify({ query: debouncedQuery }),
|
|
2064
|
+
});
|
|
2065
|
+
}, [debouncedQuery]);
|
|
1901
2066
|
|
|
1902
|
-
return (
|
|
1903
|
-
|
|
1904
|
-
onChange={ event => setQuery( event.target.value ) }
|
|
1905
|
-
/>
|
|
1906
|
-
)
|
|
1907
|
-
|
|
1908
|
-
}
|
|
2067
|
+
return <input onChange={(event) => setQuery(event.target.value)} />;
|
|
2068
|
+
};
|
|
1909
2069
|
```
|
|
1910
2070
|
|
|
1911
2071
|
</details>
|
|
@@ -1925,8 +2085,8 @@ The `Timeout` is automatically cancelled on unmount.
|
|
|
1925
2085
|
|
|
1926
2086
|
<summary style="cursor:pointer">Type Parameters</summary>
|
|
1927
2087
|
|
|
1928
|
-
| Parameter | Description
|
|
1929
|
-
|
|
2088
|
+
| Parameter | Description |
|
|
2089
|
+
| --------- | -------------------------------------------------------------- |
|
|
1930
2090
|
| `T` | An Array defining optional arguments passed to the `callback`. |
|
|
1931
2091
|
|
|
1932
2092
|
</details>
|
|
@@ -1937,15 +2097,15 @@ The `Timeout` is automatically cancelled on unmount.
|
|
|
1937
2097
|
|
|
1938
2098
|
<summary style="cursor:pointer">Parameters</summary>
|
|
1939
2099
|
|
|
1940
|
-
| Parameter
|
|
1941
|
-
|
|
1942
|
-
| `callback
|
|
1943
|
-
| `options`
|
|
1944
|
-
| `options.delay`
|
|
1945
|
-
| `options.args`
|
|
1946
|
-
| `options.autoplay`
|
|
1947
|
-
| `options.updateState` | `boolean`
|
|
1948
|
-
| `options.runOnStart`
|
|
2100
|
+
| Parameter | Type | Default | Description |
|
|
2101
|
+
| --------------------- | ----------------- | ------- | ----------------------------------------------------------------- |
|
|
2102
|
+
| `callback` | `TimerHandler<T>` | - | The function to call when the timer elapses. |
|
|
2103
|
+
| `options` | `TimerOptions<T>` | - | (Optional) An object defining custom timer options. |
|
|
2104
|
+
| `options.delay` | `number` | `1` | The number of milliseconds to wait before calling the `callback`. |
|
|
2105
|
+
| `options.args` | `T` | - | Optional arguments to pass when the `callback` is called. |
|
|
2106
|
+
| `options.autoplay` | `boolean` | `true` | Indicates whether auto start the timer. |
|
|
2107
|
+
| `options.updateState` | `boolean` | `false` | Whether to update React state about Timer running status. |
|
|
2108
|
+
| `options.runOnStart` | `boolean` | `false` | Indicates whether to execute the callback when timer starts. |
|
|
1949
2109
|
|
|
1950
2110
|
</details>
|
|
1951
2111
|
|
|
@@ -1977,22 +2137,21 @@ If `updateState` is set to `true` then the following property is added in the re
|
|
|
1977
2137
|
##### Basic usage
|
|
1978
2138
|
|
|
1979
2139
|
```tsx
|
|
1980
|
-
|
|
2140
|
+
"use client";
|
|
1981
2141
|
|
|
1982
|
-
import { useCallback } from
|
|
1983
|
-
import { useInterval } from
|
|
2142
|
+
import { useCallback } from "react";
|
|
2143
|
+
import { useInterval } from "@alessiofrittoli/react-hooks";
|
|
1984
2144
|
|
|
1985
2145
|
const MyComponent: React.FC = () => {
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
}
|
|
2146
|
+
const { stop } = useInterval(
|
|
2147
|
+
useCallback(() => {
|
|
2148
|
+
console.log("tick timer");
|
|
2149
|
+
}, []),
|
|
2150
|
+
{ delay: 1000 }
|
|
2151
|
+
);
|
|
2152
|
+
|
|
2153
|
+
return <button onClick={stop}>Stop timer</button>;
|
|
2154
|
+
};
|
|
1996
2155
|
```
|
|
1997
2156
|
|
|
1998
2157
|
---
|
|
@@ -2000,34 +2159,31 @@ const MyComponent: React.FC = () => {
|
|
|
2000
2159
|
##### Rely on state updates
|
|
2001
2160
|
|
|
2002
2161
|
```tsx
|
|
2003
|
-
|
|
2162
|
+
"use client";
|
|
2004
2163
|
|
|
2005
|
-
import { useCallback } from
|
|
2006
|
-
import { useInterval } from
|
|
2164
|
+
import { useCallback } from "react";
|
|
2165
|
+
import { useInterval } from "@alessiofrittoli/react-hooks";
|
|
2007
2166
|
|
|
2008
2167
|
const MyComponent: React.FC = () => {
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2168
|
+
const { isActive, start, stop } = useInterval(
|
|
2169
|
+
useCallback(() => {
|
|
2170
|
+
console.log("tick timer");
|
|
2171
|
+
}, []),
|
|
2172
|
+
{
|
|
2173
|
+
delay: 1000,
|
|
2174
|
+
autoplay: false,
|
|
2175
|
+
runOnStart: true,
|
|
2176
|
+
updateState: true,
|
|
2177
|
+
}
|
|
2178
|
+
);
|
|
2018
2179
|
|
|
2019
2180
|
return (
|
|
2020
2181
|
<>
|
|
2021
|
-
{
|
|
2022
|
-
|
|
2023
|
-
) }
|
|
2024
|
-
{ isActive && (
|
|
2025
|
-
<button onClick={ stop }>Stop timer</button>
|
|
2026
|
-
) }
|
|
2182
|
+
{!isActive && <button onClick={start}>Start timer</button>}
|
|
2183
|
+
{isActive && <button onClick={stop}>Stop timer</button>}
|
|
2027
2184
|
</>
|
|
2028
|
-
)
|
|
2029
|
-
|
|
2030
|
-
}
|
|
2185
|
+
);
|
|
2186
|
+
};
|
|
2031
2187
|
```
|
|
2032
2188
|
|
|
2033
2189
|
</details>
|
|
@@ -2055,8 +2211,8 @@ This is a lighter version of [`useInterval`](#useinterval) and is suggested to u
|
|
|
2055
2211
|
|
|
2056
2212
|
<summary style="cursor:pointer">Type Parameters</summary>
|
|
2057
2213
|
|
|
2058
|
-
| Parameter | Description
|
|
2059
|
-
|
|
2214
|
+
| Parameter | Description |
|
|
2215
|
+
| --------- | -------------------------------------------------------------- |
|
|
2060
2216
|
| `T` | An Array defining optional arguments passed to the `callback`. |
|
|
2061
2217
|
|
|
2062
2218
|
</details>
|
|
@@ -2067,12 +2223,12 @@ This is a lighter version of [`useInterval`](#useinterval) and is suggested to u
|
|
|
2067
2223
|
|
|
2068
2224
|
<summary style="cursor:pointer">Parameters</summary>
|
|
2069
2225
|
|
|
2070
|
-
| Parameter
|
|
2071
|
-
|
|
2072
|
-
| `callback
|
|
2073
|
-
| `options`
|
|
2074
|
-
| `options.delay` | `number`
|
|
2075
|
-
| `options.args`
|
|
2226
|
+
| Parameter | Type | Default | Description |
|
|
2227
|
+
| --------------- | ---------------------- | ------- | ----------------------------------------------------------------- |
|
|
2228
|
+
| `callback` | `TimerHandler<T>` | - | The function to call when the timer elapses. |
|
|
2229
|
+
| `options` | `BasicTimerOptions<T>` | - | (Optional) An object defining custom timer options. |
|
|
2230
|
+
| `options.delay` | `number` | `1` | The number of milliseconds to wait before calling the `callback`. |
|
|
2231
|
+
| `options.args` | `T` | - | Optional arguments to pass when the `callback` is called. |
|
|
2076
2232
|
|
|
2077
2233
|
</details>
|
|
2078
2234
|
|
|
@@ -2083,18 +2239,19 @@ This is a lighter version of [`useInterval`](#useinterval) and is suggested to u
|
|
|
2083
2239
|
<summary style="cursor:pointer">Usage</summary>
|
|
2084
2240
|
|
|
2085
2241
|
```tsx
|
|
2086
|
-
|
|
2242
|
+
"use client";
|
|
2087
2243
|
|
|
2088
|
-
import { useCallback } from
|
|
2089
|
-
import { useLightInterval } from
|
|
2244
|
+
import { useCallback } from "react";
|
|
2245
|
+
import { useLightInterval } from "@alessiofrittoli/react-hooks";
|
|
2090
2246
|
|
|
2091
2247
|
const MyComponent: React.FC = () => {
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2248
|
+
useLightInterval(
|
|
2249
|
+
useCallback(() => {
|
|
2250
|
+
console.log("tick timer");
|
|
2251
|
+
}, []),
|
|
2252
|
+
{ delay: 1000 }
|
|
2253
|
+
);
|
|
2254
|
+
};
|
|
2098
2255
|
```
|
|
2099
2256
|
|
|
2100
2257
|
</details>
|
|
@@ -2122,8 +2279,8 @@ The `Timeout` is automatically cancelled on unmount.
|
|
|
2122
2279
|
|
|
2123
2280
|
<summary style="cursor:pointer">Type Parameters</summary>
|
|
2124
2281
|
|
|
2125
|
-
| Parameter | Description
|
|
2126
|
-
|
|
2282
|
+
| Parameter | Description |
|
|
2283
|
+
| --------- | -------------------------------------------------------------- |
|
|
2127
2284
|
| `T` | An Array defining optional arguments passed to the `callback`. |
|
|
2128
2285
|
|
|
2129
2286
|
</details>
|
|
@@ -2134,15 +2291,15 @@ The `Timeout` is automatically cancelled on unmount.
|
|
|
2134
2291
|
|
|
2135
2292
|
<summary style="cursor:pointer">Parameters</summary>
|
|
2136
2293
|
|
|
2137
|
-
| Parameter
|
|
2138
|
-
|
|
2139
|
-
| `callback
|
|
2140
|
-
| `options`
|
|
2141
|
-
| `options.delay`
|
|
2142
|
-
| `options.args`
|
|
2143
|
-
| `options.autoplay`
|
|
2144
|
-
| `options.updateState` | `boolean`
|
|
2145
|
-
| `options.runOnStart`
|
|
2294
|
+
| Parameter | Type | Default | Description |
|
|
2295
|
+
| --------------------- | ----------------- | ------- | ----------------------------------------------------------------- |
|
|
2296
|
+
| `callback` | `TimerHandler<T>` | - | The function to call when the timer elapses. |
|
|
2297
|
+
| `options` | `TimerOptions<T>` | - | (Optional) An object defining custom timer options. |
|
|
2298
|
+
| `options.delay` | `number` | `1` | The number of milliseconds to wait before calling the `callback`. |
|
|
2299
|
+
| `options.args` | `T` | - | Optional arguments to pass when the `callback` is called. |
|
|
2300
|
+
| `options.autoplay` | `boolean` | `true` | Indicates whether auto start the timer. |
|
|
2301
|
+
| `options.updateState` | `boolean` | `false` | Whether to update React state about Timer running status. |
|
|
2302
|
+
| `options.runOnStart` | `boolean` | `false` | Indicates whether to execute the callback when timer starts. |
|
|
2146
2303
|
|
|
2147
2304
|
</details>
|
|
2148
2305
|
|
|
@@ -2174,22 +2331,21 @@ If `updateState` is set to `true` then the following property is added in the re
|
|
|
2174
2331
|
##### Basic usage
|
|
2175
2332
|
|
|
2176
2333
|
```tsx
|
|
2177
|
-
|
|
2334
|
+
"use client";
|
|
2178
2335
|
|
|
2179
|
-
import { useCallback } from
|
|
2180
|
-
import { useTimeout } from
|
|
2336
|
+
import { useCallback } from "react";
|
|
2337
|
+
import { useTimeout } from "@alessiofrittoli/react-hooks";
|
|
2181
2338
|
|
|
2182
2339
|
const MyComponent: React.FC = () => {
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
}
|
|
2340
|
+
const { stop } = useTimeout(
|
|
2341
|
+
useCallback(() => {
|
|
2342
|
+
console.log("tick timer");
|
|
2343
|
+
}, []),
|
|
2344
|
+
{ delay: 1000 }
|
|
2345
|
+
);
|
|
2346
|
+
|
|
2347
|
+
return <button onClick={stop}>Stop timer</button>;
|
|
2348
|
+
};
|
|
2193
2349
|
```
|
|
2194
2350
|
|
|
2195
2351
|
---
|
|
@@ -2197,34 +2353,31 @@ const MyComponent: React.FC = () => {
|
|
|
2197
2353
|
##### Rely on state updates
|
|
2198
2354
|
|
|
2199
2355
|
```tsx
|
|
2200
|
-
|
|
2356
|
+
"use client";
|
|
2201
2357
|
|
|
2202
|
-
import { useCallback } from
|
|
2203
|
-
import { useTimeout } from
|
|
2358
|
+
import { useCallback } from "react";
|
|
2359
|
+
import { useTimeout } from "@alessiofrittoli/react-hooks";
|
|
2204
2360
|
|
|
2205
2361
|
const MyComponent: React.FC = () => {
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2362
|
+
const { isActive, start, stop } = useTimeout(
|
|
2363
|
+
useCallback(() => {
|
|
2364
|
+
console.log("tick timer");
|
|
2365
|
+
}, []),
|
|
2366
|
+
{
|
|
2367
|
+
delay: 1000,
|
|
2368
|
+
autoplay: false,
|
|
2369
|
+
runOnStart: true,
|
|
2370
|
+
updateState: true,
|
|
2371
|
+
}
|
|
2372
|
+
);
|
|
2215
2373
|
|
|
2216
2374
|
return (
|
|
2217
2375
|
<>
|
|
2218
|
-
{
|
|
2219
|
-
|
|
2220
|
-
) }
|
|
2221
|
-
{ isActive && (
|
|
2222
|
-
<button onClick={ stop }>Stop timer</button>
|
|
2223
|
-
) }
|
|
2376
|
+
{!isActive && <button onClick={start}>Start timer</button>}
|
|
2377
|
+
{isActive && <button onClick={stop}>Stop timer</button>}
|
|
2224
2378
|
</>
|
|
2225
|
-
)
|
|
2226
|
-
|
|
2227
|
-
}
|
|
2379
|
+
);
|
|
2380
|
+
};
|
|
2228
2381
|
```
|
|
2229
2382
|
|
|
2230
2383
|
</details>
|
|
@@ -2241,8 +2394,8 @@ This is a lighter version of [`useTimeout`](#usetimeout) and is suggested to use
|
|
|
2241
2394
|
|
|
2242
2395
|
<summary style="cursor:pointer">Type Parameters</summary>
|
|
2243
2396
|
|
|
2244
|
-
| Parameter | Description
|
|
2245
|
-
|
|
2397
|
+
| Parameter | Description |
|
|
2398
|
+
| --------- | -------------------------------------------------------------- |
|
|
2246
2399
|
| `T` | An Array defining optional arguments passed to the `callback`. |
|
|
2247
2400
|
|
|
2248
2401
|
</details>
|
|
@@ -2253,12 +2406,12 @@ This is a lighter version of [`useTimeout`](#usetimeout) and is suggested to use
|
|
|
2253
2406
|
|
|
2254
2407
|
<summary style="cursor:pointer">Parameters</summary>
|
|
2255
2408
|
|
|
2256
|
-
| Parameter
|
|
2257
|
-
|
|
2258
|
-
| `callback
|
|
2259
|
-
| `options`
|
|
2260
|
-
| `options.delay` | `number`
|
|
2261
|
-
| `options.args`
|
|
2409
|
+
| Parameter | Type | Default | Description |
|
|
2410
|
+
| --------------- | ---------------------- | ------- | ----------------------------------------------------------------- |
|
|
2411
|
+
| `callback` | `TimerHandler<T>` | - | The function to call when the timer elapses. |
|
|
2412
|
+
| `options` | `BasicTimerOptions<T>` | - | (Optional) An object defining custom timer options. |
|
|
2413
|
+
| `options.delay` | `number` | `1` | The number of milliseconds to wait before calling the `callback`. |
|
|
2414
|
+
| `options.args` | `T` | - | Optional arguments to pass when the `callback` is called. |
|
|
2262
2415
|
|
|
2263
2416
|
</details>
|
|
2264
2417
|
|
|
@@ -2269,18 +2422,19 @@ This is a lighter version of [`useTimeout`](#usetimeout) and is suggested to use
|
|
|
2269
2422
|
<summary style="cursor:pointer">Usage</summary>
|
|
2270
2423
|
|
|
2271
2424
|
```tsx
|
|
2272
|
-
|
|
2425
|
+
"use client";
|
|
2273
2426
|
|
|
2274
|
-
import { useCallback } from
|
|
2275
|
-
import { useLightTimeout } from
|
|
2427
|
+
import { useCallback } from "react";
|
|
2428
|
+
import { useLightTimeout } from "@alessiofrittoli/react-hooks";
|
|
2276
2429
|
|
|
2277
2430
|
const MyComponent: React.FC = () => {
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2431
|
+
useLightTimeout(
|
|
2432
|
+
useCallback(() => {
|
|
2433
|
+
console.log("tick timer");
|
|
2434
|
+
}, []),
|
|
2435
|
+
{ delay: 1000 }
|
|
2436
|
+
);
|
|
2437
|
+
};
|
|
2284
2438
|
```
|
|
2285
2439
|
|
|
2286
2440
|
</details>
|