@aweebit/react-essentials 0.5.4 → 0.7.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.
Files changed (59) hide show
  1. package/README.md +836 -0
  2. package/dist/hooks/index.d.ts +5 -0
  3. package/dist/hooks/index.d.ts.map +1 -0
  4. package/dist/hooks/index.js +5 -0
  5. package/dist/hooks/index.js.map +1 -0
  6. package/dist/hooks/useEventListener.d.ts +65 -11
  7. package/dist/hooks/useEventListener.d.ts.map +1 -1
  8. package/dist/hooks/useEventListener.js +49 -18
  9. package/dist/hooks/useEventListener.js.map +1 -1
  10. package/dist/hooks/useForceUpdate.d.ts +52 -4
  11. package/dist/hooks/useForceUpdate.d.ts.map +1 -1
  12. package/dist/hooks/useForceUpdate.js +58 -9
  13. package/dist/hooks/useForceUpdate.js.map +1 -1
  14. package/dist/hooks/useReducerWithDeps.d.ts +17 -11
  15. package/dist/hooks/useReducerWithDeps.d.ts.map +1 -1
  16. package/dist/hooks/useReducerWithDeps.js +14 -12
  17. package/dist/hooks/useReducerWithDeps.js.map +1 -1
  18. package/dist/hooks/useStateWithDeps.d.ts +41 -7
  19. package/dist/hooks/useStateWithDeps.d.ts.map +1 -1
  20. package/dist/hooks/useStateWithDeps.js +47 -15
  21. package/dist/hooks/useStateWithDeps.js.map +1 -1
  22. package/dist/index.d.ts +2 -5
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +2 -5
  25. package/dist/index.js.map +1 -1
  26. package/dist/misc/createSafeContext.d.ts +85 -0
  27. package/dist/misc/createSafeContext.d.ts.map +1 -0
  28. package/dist/misc/createSafeContext.js +77 -0
  29. package/dist/misc/createSafeContext.js.map +1 -0
  30. package/dist/misc/index.d.ts +2 -0
  31. package/dist/misc/index.d.ts.map +1 -0
  32. package/dist/misc/index.js +2 -0
  33. package/dist/misc/index.js.map +1 -0
  34. package/dist/utils.d.ts +7 -0
  35. package/dist/utils.d.ts.map +1 -0
  36. package/dist/{utils/index.js → utils.js} +1 -2
  37. package/dist/utils.js.map +1 -0
  38. package/package.json +25 -15
  39. package/src/hooks/index.ts +4 -0
  40. package/src/hooks/useEventListener.ts +201 -0
  41. package/src/hooks/useForceUpdate.ts +91 -0
  42. package/{lib → src}/hooks/useReducerWithDeps.ts +27 -18
  43. package/src/hooks/useStateWithDeps.ts +111 -0
  44. package/src/index.ts +2 -0
  45. package/src/misc/createSafeContext.ts +116 -0
  46. package/src/misc/index.ts +1 -0
  47. package/{lib/utils/index.ts → src/utils.ts} +9 -2
  48. package/dist/hooks/useIsomorphicLayoutEffect.d.ts +0 -4
  49. package/dist/hooks/useIsomorphicLayoutEffect.d.ts.map +0 -1
  50. package/dist/hooks/useIsomorphicLayoutEffect.js +0 -5
  51. package/dist/hooks/useIsomorphicLayoutEffect.js.map +0 -1
  52. package/dist/utils/index.d.ts +0 -5
  53. package/dist/utils/index.d.ts.map +0 -1
  54. package/dist/utils/index.js.map +0 -1
  55. package/lib/hooks/useEventListener.ts +0 -101
  56. package/lib/hooks/useForceUpdate.ts +0 -40
  57. package/lib/hooks/useIsomorphicLayoutEffect.ts +0 -7
  58. package/lib/hooks/useStateWithDeps.ts +0 -79
  59. package/lib/index.ts +0 -5
package/README.md ADDED
@@ -0,0 +1,836 @@
1
+ # @aweebit/react-essentials
2
+
3
+ [![NPM Version](https://img.shields.io/npm/v/%40aweebit%2Freact-essentials)](https://www.npmjs.com/package/@aweebit/react-essentials)
4
+
5
+ - [useEventListener()](#useeventlistener)
6
+ - [useForceUpdate()](#useforceupdate)
7
+ - [useReducerWithDeps()](#usereducerwithdeps)
8
+ - [useStateWithDeps()](#usestatewithdeps)
9
+ - [createSafeContext()](#createsafecontext)
10
+ - [RestrictedContext](#restrictedcontext)
11
+ - [SafeContext](#safecontext)
12
+
13
+ ## useEventListener()
14
+
15
+ Adds `handler` as a listener for the event `eventName` of `target` with the
16
+ provided `options` applied
17
+
18
+ If `target` is not provided, `window` is used instead.
19
+
20
+ If `target` is `null`, no event listener is added. This is useful when
21
+ working with DOM element refs, or when the event listener needs to be removed
22
+ temporarily.
23
+
24
+ ### Example
25
+
26
+ ```tsx
27
+ useEventListener('resize', () => {
28
+ console.log(window.innerWidth, window.innerHeight);
29
+ });
30
+
31
+ useEventListener(document, 'visibilitychange', () => {
32
+ console.log(document.visibilityState);
33
+ });
34
+
35
+ const buttonRef = useRef<HTMLButtonElement>(null);
36
+ useEventListener(buttonRef.current, 'click', () => console.log('click'));
37
+ ```
38
+
39
+ ### Call Signature
40
+
41
+ ```ts
42
+ function useEventListener<K>(eventName, handler, options?): void;
43
+ ```
44
+
45
+ Defined in: [hooks/useEventListener.ts:99](https://github.com/aweebit/react-essentials/blob/v0.7.0/src/hooks/useEventListener.ts#L99)
46
+
47
+ #### Type Parameters
48
+
49
+ <table>
50
+ <thead>
51
+ <tr>
52
+ <th>Type Parameter</th>
53
+ </tr>
54
+ </thead>
55
+ <tbody>
56
+ <tr>
57
+ <td>
58
+
59
+ `K` _extends_ keyof `WindowEventMap`
60
+
61
+ </td>
62
+ </tr>
63
+ </tbody>
64
+ </table>
65
+
66
+ #### Parameters
67
+
68
+ <table>
69
+ <thead>
70
+ <tr>
71
+ <th>Parameter</th>
72
+ <th>Type</th>
73
+ </tr>
74
+ </thead>
75
+ <tbody>
76
+ <tr>
77
+ <td>
78
+
79
+ `eventName`
80
+
81
+ </td>
82
+ <td>
83
+
84
+ `K`
85
+
86
+ </td>
87
+ </tr>
88
+ <tr>
89
+ <td>
90
+
91
+ `handler`
92
+
93
+ </td>
94
+ <td>
95
+
96
+ (`this`, `event`) => `void`
97
+
98
+ </td>
99
+ </tr>
100
+ <tr>
101
+ <td>
102
+
103
+ `options?`
104
+
105
+ </td>
106
+ <td>
107
+
108
+ `boolean` \| `AddEventListenerOptions`
109
+
110
+ </td>
111
+ </tr>
112
+ </tbody>
113
+ </table>
114
+
115
+ #### Returns
116
+
117
+ `void`
118
+
119
+ #### See
120
+
121
+ [`useEventListener`](#useeventlistener)
122
+
123
+ ### Call Signature
124
+
125
+ ```ts
126
+ function useEventListener<T>(target, eventName, handler, options?): void;
127
+ ```
128
+
129
+ Defined in: [hooks/useEventListener.ts:108](https://github.com/aweebit/react-essentials/blob/v0.7.0/src/hooks/useEventListener.ts#L108)
130
+
131
+ #### Type Parameters
132
+
133
+ <table>
134
+ <thead>
135
+ <tr>
136
+ <th>Type Parameter</th>
137
+ </tr>
138
+ </thead>
139
+ <tbody>
140
+ <tr>
141
+ <td>
142
+
143
+ `T` _extends_ `EventTarget`
144
+
145
+ </td>
146
+ </tr>
147
+ </tbody>
148
+ </table>
149
+
150
+ #### Parameters
151
+
152
+ <table>
153
+ <thead>
154
+ <tr>
155
+ <th>Parameter</th>
156
+ <th>Type</th>
157
+ </tr>
158
+ </thead>
159
+ <tbody>
160
+ <tr>
161
+ <td>
162
+
163
+ `target`
164
+
165
+ </td>
166
+ <td>
167
+
168
+ `null` \| `T`
169
+
170
+ </td>
171
+ </tr>
172
+ <tr>
173
+ <td>
174
+
175
+ `eventName`
176
+
177
+ </td>
178
+ <td>
179
+
180
+ `string`
181
+
182
+ </td>
183
+ </tr>
184
+ <tr>
185
+ <td>
186
+
187
+ `handler`
188
+
189
+ </td>
190
+ <td>
191
+
192
+ (`this`, `event`) => `void`
193
+
194
+ </td>
195
+ </tr>
196
+ <tr>
197
+ <td>
198
+
199
+ `options?`
200
+
201
+ </td>
202
+ <td>
203
+
204
+ `boolean` \| `AddEventListenerOptions`
205
+
206
+ </td>
207
+ </tr>
208
+ </tbody>
209
+ </table>
210
+
211
+ #### Returns
212
+
213
+ `void`
214
+
215
+ #### See
216
+
217
+ [`useEventListener`](#useeventlistener)
218
+
219
+ ---
220
+
221
+ ## useForceUpdate()
222
+
223
+ ```ts
224
+ function useForceUpdate(callback?): [() => void, bigint];
225
+ ```
226
+
227
+ Defined in: [hooks/useForceUpdate.ts:81](https://github.com/aweebit/react-essentials/blob/v0.7.0/src/hooks/useForceUpdate.ts#L81)
228
+
229
+ Enables you to imperatively trigger re-rendering of components
230
+
231
+ This hook is designed in the most general way possible in order to cover all
232
+ imaginable use cases.
233
+
234
+ ### Example
235
+
236
+ Sometimes, React's immutability constraints mean too much unnecessary copying
237
+ of data when new data arrives at a high frequency. In such cases, it might be
238
+ desirable to ignore the constraints by embracing imperative patterns.
239
+ Here is an example of a scenario where that can make sense:
240
+
241
+ ```tsx
242
+ type SensorData = { timestamp: number; value: number };
243
+ const sensorDataRef = useRef<SensorData[]>([]);
244
+ const mostRecentSensorDataTimestampRef = useRef<number>(0);
245
+
246
+ const [forceUpdate, updateCount] = useForceUpdate();
247
+ // Limiting the frequency of forced re-renders with some throttle function:
248
+ const throttledForceUpdateRef = useRef(throttle(forceUpdate));
249
+
250
+ useEffect(() => {
251
+ return sensorDataObservable.subscribe((data: SensorData) => {
252
+ // Imagine new sensor data arrives every 1 millisecond. If we were following
253
+ // React's immutability rules by creating a new array every time, the data
254
+ // that's already there would have to be copied many times before the new
255
+ // data would even get a chance to be reflected in the UI for the first time
256
+ // because it typically takes much longer than 1 millisecond for a new frame
257
+ // to be displayed. To prevent the waste of computational resources, we just
258
+ // mutate the existing array every time instead:
259
+ sensorDataRef.current.push(data);
260
+ if (data.timestamp > mostRecentSensorDataTimestampRef.current) {
261
+ mostRecentSensorDataTimestampRef.current = data.timestamp;
262
+ }
263
+ throttledForceUpdateRef.current();
264
+ });
265
+ }, []);
266
+
267
+ const [timeWindow, setTimeWindow] = useState(1000);
268
+ const selectedSensorData = useMemo(
269
+ () => {
270
+ // Keep this line if you don't want to disable the
271
+ // react-hooks/exhaustive-deps ESLint rule:
272
+ updateCount;
273
+ const threshold = mostRecentSensorDataTimestampRef.current - timeWindow;
274
+ return sensorDataRef.current.filter(
275
+ ({ timestamp }) => timestamp >= threshold,
276
+ );
277
+ },
278
+ // sensorDataRef.current always references the same array, so listing it as a
279
+ // dependency is pointless. Instead, updateCount should be used:
280
+ [updateCount, timeWindow],
281
+ );
282
+ ```
283
+
284
+ ### Parameters
285
+
286
+ <table>
287
+ <thead>
288
+ <tr>
289
+ <th>Parameter</th>
290
+ <th>Type</th>
291
+ <th>Description</th>
292
+ </tr>
293
+ </thead>
294
+ <tbody>
295
+ <tr>
296
+ <td>
297
+
298
+ `callback?`
299
+
300
+ </td>
301
+ <td>
302
+
303
+ () => `void`
304
+
305
+ </td>
306
+ <td>
307
+
308
+ An optional callback function to call during renders that
309
+ were triggered with `forceUpdate()`
310
+
311
+ Can be used for conditionally calling state setters when state needs to be
312
+ reset. That is legal and better than using effects (see
313
+ [You Might Not Need an Effect \> Adjusting some state when a prop changes](https://react.dev/learn/-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes)),
314
+ but can often be avoided by using [`useStateWithDeps`](#usestatewithdeps) or
315
+ [`useReducerWithDeps`](#usereducerwithdeps).
316
+
317
+ Important: the callback function is called once per render, not once per
318
+ `forceUpdate` call! If React batches `forceUpdate` calls, then it will only
319
+ be called once.
320
+
321
+ </td>
322
+ </tr>
323
+ </tbody>
324
+ </table>
325
+
326
+ ### Returns
327
+
328
+ \[() => `void`, `bigint`\]
329
+
330
+ An array with the following two elements:
331
+
332
+ 1. A `forceUpdate` function that triggers a re-render
333
+ 2. The number of times `forceUpdate` has been called so far
334
+
335
+ ---
336
+
337
+ ## useReducerWithDeps()
338
+
339
+ ```ts
340
+ function useReducerWithDeps<S, A>(
341
+ reducer,
342
+ initialState,
343
+ deps,
344
+ ): [S, ActionDispatch<A>];
345
+ ```
346
+
347
+ Defined in: [hooks/useReducerWithDeps.ts:52](https://github.com/aweebit/react-essentials/blob/v0.7.0/src/hooks/useReducerWithDeps.ts#L52)
348
+
349
+ `useReducer` hook with an additional dependency array `deps` that resets the
350
+ state to `initialState` when dependencies change
351
+
352
+ For motivation and examples, see
353
+ https://github.com/facebook/react/issues/33041.
354
+
355
+ ### On linter support
356
+
357
+ The `react-hooks/exhaustive-deps` ESLint rule doesn't support hooks where
358
+ the dependency array parameter is at any other position than the second.
359
+ However, as we would like to keep the hook as compatible with `useReducer` as
360
+ possible, we don't want to artificially change the parameter's position.
361
+ Therefore, there will be no warnings about missing dependencies.
362
+ Because of that, additional caution is advised!
363
+ Be sure to check that no dependencies are missing from the `deps` array.
364
+
365
+ Related issue: [https://github.com/facebook/react/issues/25443](https://github.com/facebook/react/issues/25443).
366
+
367
+ Unlike `eslint-plugin-react-hooks` maintained by React's team, the unofficial
368
+ `useExhaustiveDependencies` rule provided for Biome by Biome's team
369
+ does actually have support for dependency arrays at other positions, see
370
+ [useExhaustiveDependencies \> Options \> Validating dependencies](https://biomejs.dev/linter/rules/use-exhaustive-dependencies/#validating-dependencies).
371
+
372
+ ### Type Parameters
373
+
374
+ <table>
375
+ <thead>
376
+ <tr>
377
+ <th>Type Parameter</th>
378
+ </tr>
379
+ </thead>
380
+ <tbody>
381
+ <tr>
382
+ <td>
383
+
384
+ `S`
385
+
386
+ </td>
387
+ </tr>
388
+ <tr>
389
+ <td>
390
+
391
+ `A` _extends_ `AnyActionArg`
392
+
393
+ </td>
394
+ </tr>
395
+ </tbody>
396
+ </table>
397
+
398
+ ### Parameters
399
+
400
+ <table>
401
+ <thead>
402
+ <tr>
403
+ <th>Parameter</th>
404
+ <th>Type</th>
405
+ <th>Description</th>
406
+ </tr>
407
+ </thead>
408
+ <tbody>
409
+ <tr>
410
+ <td>
411
+
412
+ `reducer`
413
+
414
+ </td>
415
+ <td>
416
+
417
+ (`prevState`, ...`args`) => `S`
418
+
419
+ </td>
420
+ <td>
421
+
422
+ The reducer function that specifies how the state gets updated
423
+
424
+ </td>
425
+ </tr>
426
+ <tr>
427
+ <td>
428
+
429
+ `initialState`
430
+
431
+ </td>
432
+ <td>
433
+
434
+ `S` \| (`previousState?`) => `S`
435
+
436
+ </td>
437
+ <td>
438
+
439
+ The value to which the state is set when the component is
440
+ mounted or dependencies change
441
+
442
+ It can also be a function that returns a state value. If the state is reset
443
+ due to a change of dependencies, this function will be passed the previous
444
+ state as its argument (will be `undefined` in the first call upon mount).
445
+
446
+ </td>
447
+ </tr>
448
+ <tr>
449
+ <td>
450
+
451
+ `deps`
452
+
453
+ </td>
454
+ <td>
455
+
456
+ `DependencyList`
457
+
458
+ </td>
459
+ <td>
460
+
461
+ Dependencies that reset the state to `initialState`
462
+
463
+ </td>
464
+ </tr>
465
+ </tbody>
466
+ </table>
467
+
468
+ ### Returns
469
+
470
+ \[`S`, `ActionDispatch`\<`A`\>\]
471
+
472
+ ---
473
+
474
+ ## useStateWithDeps()
475
+
476
+ ```ts
477
+ function useStateWithDeps<S>(
478
+ initialState,
479
+ deps,
480
+ ): [S, Dispatch<SetStateAction<S>>];
481
+ ```
482
+
483
+ Defined in: [hooks/useStateWithDeps.ts:66](https://github.com/aweebit/react-essentials/blob/v0.7.0/src/hooks/useStateWithDeps.ts#L66)
484
+
485
+ `useState` hook with an additional dependency array `deps` that resets the
486
+ state to `initialState` when dependencies change
487
+
488
+ For motivation and more examples, see
489
+ https://github.com/facebook/react/issues/33041.
490
+
491
+ ### Example
492
+
493
+ ```tsx
494
+ type Activity = 'breakfast' | 'exercise' | 'swim' | 'board games' | 'dinner';
495
+
496
+ const timeOfDayOptions = ['morning', 'afternoon', 'evening'] as const;
497
+ type TimeOfDay = (typeof timeOfDayOptions)[number];
498
+
499
+ const activityOptionsByTimeOfDay: {
500
+ [K in TimeOfDay]: [Activity, ...Activity[]];
501
+ } = {
502
+ morning: ['breakfast', 'exercise', 'swim'],
503
+ afternoon: ['exercise', 'swim', 'board games'],
504
+ evening: ['board games', 'dinner'],
505
+ };
506
+
507
+ export function Example() {
508
+ const [timeOfDay, setTimeOfDay] = useState<TimeOfDay>('morning');
509
+
510
+ const activityOptions = activityOptionsByTimeOfDay[timeOfDay];
511
+ const [activity, setActivity] = useStateWithDeps<Activity>(
512
+ (prev) => {
513
+ // Make sure activity is always valid for the current timeOfDay value,
514
+ // but also don't reset it unless necessary:
515
+ return prev && activityOptions.includes(prev) ? prev : activityOptions[0];
516
+ },
517
+ [activityOptions],
518
+ );
519
+
520
+ return '...';
521
+ }
522
+ ```
523
+
524
+ ### Type Parameters
525
+
526
+ <table>
527
+ <thead>
528
+ <tr>
529
+ <th>Type Parameter</th>
530
+ </tr>
531
+ </thead>
532
+ <tbody>
533
+ <tr>
534
+ <td>
535
+
536
+ `S`
537
+
538
+ </td>
539
+ </tr>
540
+ </tbody>
541
+ </table>
542
+
543
+ ### Parameters
544
+
545
+ <table>
546
+ <thead>
547
+ <tr>
548
+ <th>Parameter</th>
549
+ <th>Type</th>
550
+ <th>Description</th>
551
+ </tr>
552
+ </thead>
553
+ <tbody>
554
+ <tr>
555
+ <td>
556
+
557
+ `initialState`
558
+
559
+ </td>
560
+ <td>
561
+
562
+ `S` \| (`previousState?`) => `S`
563
+
564
+ </td>
565
+ <td>
566
+
567
+ The value to which the state is set when the component is
568
+ mounted or dependencies change
569
+
570
+ It can also be a function that returns a state value. If the state is reset
571
+ due to a change of dependencies, this function will be passed the previous
572
+ state as its argument (will be `undefined` in the first call upon mount).
573
+
574
+ </td>
575
+ </tr>
576
+ <tr>
577
+ <td>
578
+
579
+ `deps`
580
+
581
+ </td>
582
+ <td>
583
+
584
+ `DependencyList`
585
+
586
+ </td>
587
+ <td>
588
+
589
+ Dependencies that reset the state to `initialState`
590
+
591
+ </td>
592
+ </tr>
593
+ </tbody>
594
+ </table>
595
+
596
+ ### Returns
597
+
598
+ \[`S`, `Dispatch`\<`SetStateAction`\<`S`\>\>\]
599
+
600
+ ---
601
+
602
+ ## createSafeContext()
603
+
604
+ ```ts
605
+ function createSafeContext<T>(): <DisplayName>(
606
+ displayName,
607
+ ) => SafeContext<DisplayName, T>;
608
+ ```
609
+
610
+ Defined in: [misc/createSafeContext.ts:89](https://github.com/aweebit/react-essentials/blob/v0.7.0/src/misc/createSafeContext.ts#L89)
611
+
612
+ For a given type `T`, returns a function that produces both a context of that
613
+ type and a hook that returns the current context value if one was provided,
614
+ or throws an error otherwise
615
+
616
+ The advantages over vanilla `createContext` are that no default value has to
617
+ be provided, and that a meaningful context name is displayed in dev tools
618
+ instead of generic `Context.Provider`.
619
+
620
+ ### Example
621
+
622
+ ```tsx
623
+ enum Direction {
624
+ Up,
625
+ Down,
626
+ Left,
627
+ Right,
628
+ }
629
+
630
+ // Before
631
+ const DirectionContext = createContext<Direction | undefined>(undefined);
632
+ DirectionContext.displayName = 'DirectionContext';
633
+
634
+ const useDirection = () => {
635
+ const direction = useContext(DirectionContext);
636
+ if (direction === undefined) {
637
+ // Called outside of a <DirectionContext.Provider> boundary!
638
+ // Or maybe undefined was explicitly provided as the context value
639
+ // (ideally that shouldn't be allowed, but it is because we had to include
640
+ // undefined in the context type so as to provide a meaningful default)
641
+ throw new Error('No DirectionContext value was provided');
642
+ }
643
+ // Thanks to the undefined check, the type is now narrowed down to Direction
644
+ return direction;
645
+ };
646
+
647
+ // After
648
+ const { DirectionContext, useDirection } =
649
+ createSafeContext<Direction>()('Direction'); // That's it :)
650
+
651
+ const Parent = () => (
652
+ // Providing undefined as the value is not allowed 👍
653
+ <Direction.Provider value={Direction.Up}>
654
+ <Child />
655
+ </Direction.Provider>
656
+ );
657
+
658
+ const Child = () => `Current direction: ${Direction[useDirection()]}`;
659
+ ```
660
+
661
+ ### Type Parameters
662
+
663
+ <table>
664
+ <thead>
665
+ <tr>
666
+ <th>Type Parameter</th>
667
+ <th>Default type</th>
668
+ </tr>
669
+ </thead>
670
+ <tbody>
671
+ <tr>
672
+ <td>
673
+
674
+ `T`
675
+
676
+ </td>
677
+ <td>
678
+
679
+ `never`
680
+
681
+ </td>
682
+ </tr>
683
+ </tbody>
684
+ </table>
685
+
686
+ ### Returns
687
+
688
+ A function that accepts a single string argument `displayName` (e.g.
689
+ `"Direction"`) and returns an object with the following properties:
690
+
691
+ - `` `${displayName}Context` `` (e.g. `DirectionContext`): the context
692
+ - `` `use${displayName}` `` (e.g. `useDirection`): a hook that returns the
693
+ current context value if one was provided, or throws an error otherwise
694
+
695
+ ```ts
696
+ <DisplayName>(displayName): SafeContext<DisplayName, T>;
697
+ ```
698
+
699
+ #### Type Parameters
700
+
701
+ <table>
702
+ <thead>
703
+ <tr>
704
+ <th>Type Parameter</th>
705
+ </tr>
706
+ </thead>
707
+ <tbody>
708
+ <tr>
709
+ <td>
710
+
711
+ `DisplayName` _extends_ `string`
712
+
713
+ </td>
714
+ </tr>
715
+ </tbody>
716
+ </table>
717
+
718
+ #### Parameters
719
+
720
+ <table>
721
+ <thead>
722
+ <tr>
723
+ <th>Parameter</th>
724
+ <th>Type</th>
725
+ </tr>
726
+ </thead>
727
+ <tbody>
728
+ <tr>
729
+ <td>
730
+
731
+ `displayName`
732
+
733
+ </td>
734
+ <td>
735
+
736
+ \[`T`\] _extends_ \[`never`\] ? `never` : `ArgumentFallback`\<`DisplayName`, `never`, `string`\>
737
+
738
+ </td>
739
+ </tr>
740
+ </tbody>
741
+ </table>
742
+
743
+ #### Returns
744
+
745
+ [`SafeContext`](#safecontext)\<`DisplayName`, `T`\>
746
+
747
+ ---
748
+
749
+ ## RestrictedContext
750
+
751
+ ```ts
752
+ type RestrictedContext<T> =
753
+ Context<T> extends Provider<T>
754
+ ? {
755
+ Provider: Provider<T>;
756
+ displayName: string;
757
+ } & Provider<T>
758
+ : {
759
+ Provider: Provider<T>;
760
+ displayName: string;
761
+ };
762
+ ```
763
+
764
+ Defined in: [misc/createSafeContext.ts:17](https://github.com/aweebit/react-essentials/blob/v0.7.0/src/misc/createSafeContext.ts#L17)
765
+
766
+ A React context with a required `displayName` and the obsolete `Consumer`
767
+ property purposefully omitted so that it is impossible to pass the context
768
+ as an argument to `useContext` or `use` (the hook produced with
769
+ [`createSafeContext`](#createsafecontext) should be used instead)
770
+
771
+ ### Type Parameters
772
+
773
+ <table>
774
+ <thead>
775
+ <tr>
776
+ <th>Type Parameter</th>
777
+ </tr>
778
+ </thead>
779
+ <tbody>
780
+ <tr>
781
+ <td>
782
+
783
+ `T`
784
+
785
+ </td>
786
+ </tr>
787
+ </tbody>
788
+ </table>
789
+
790
+ ### See
791
+
792
+ [`createSafeContext`](#createsafecontext)
793
+
794
+ ---
795
+
796
+ ## SafeContext
797
+
798
+ ```ts
799
+ type SafeContext<DisplayName, T> = {
800
+ [K in `${DisplayName}Context`]: RestrictedContext<T>;
801
+ } & { [K in `use${DisplayName}`]: () => T };
802
+ ```
803
+
804
+ Defined in: [misc/createSafeContext.ts:27](https://github.com/aweebit/react-essentials/blob/v0.7.0/src/misc/createSafeContext.ts#L27)
805
+
806
+ The return type of [`createSafeContext`](#createsafecontext)
807
+
808
+ ### Type Parameters
809
+
810
+ <table>
811
+ <thead>
812
+ <tr>
813
+ <th>Type Parameter</th>
814
+ </tr>
815
+ </thead>
816
+ <tbody>
817
+ <tr>
818
+ <td>
819
+
820
+ `DisplayName` _extends_ `string`
821
+
822
+ </td>
823
+ </tr>
824
+ <tr>
825
+ <td>
826
+
827
+ `T`
828
+
829
+ </td>
830
+ </tr>
831
+ </tbody>
832
+ </table>
833
+
834
+ ### See
835
+
836
+ [`createSafeContext`](#createsafecontext)