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