react-shared-states 1.0.8 → 1.0.12
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 +155 -91
- package/dist/{SharedData.d.ts → SharedValuesManager.d.ts} +28 -17
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/use-shared-function.d.ts +37 -12
- package/dist/hooks/use-shared-state.d.ts +22 -3
- package/dist/hooks/use-shared-subscription.d.ts +44 -16
- package/dist/main.esm.js +480 -395
- package/dist/main.min.js +5 -5
- package/dist/types.d.ts +2 -1
- package/package.json +9 -2
- package/tests/index.test.tsx +309 -5
- package/pnpm-workspace.yaml +0 -2
package/README.md
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
# React Shared States
|
|
3
2
|
|
|
4
3
|
**_Global state made as simple as useState, with zero config, built-in async caching, and automatic scoping._**
|
|
@@ -24,7 +23,7 @@ Tiny, ergonomic, convention‑over‑configuration state, async function, and re
|
|
|
24
23
|
* Predictable: key + scope ⇒ value. That’s it.
|
|
25
24
|
|
|
26
25
|
|
|
27
|
-
##
|
|
26
|
+
## Install
|
|
28
27
|
|
|
29
28
|
```sh
|
|
30
29
|
npm install react-shared-states
|
|
@@ -34,7 +33,7 @@ or
|
|
|
34
33
|
pnpm add react-shared-states
|
|
35
34
|
```
|
|
36
35
|
|
|
37
|
-
##
|
|
36
|
+
## 60‑Second TL;DR
|
|
38
37
|
```tsx
|
|
39
38
|
import { useSharedState } from 'react-shared-states';
|
|
40
39
|
|
|
@@ -197,66 +196,105 @@ export default function App(){
|
|
|
197
196
|
```
|
|
198
197
|
|
|
199
198
|
|
|
200
|
-
##
|
|
201
|
-
| Concept | Summary
|
|
202
|
-
|
|
203
|
-
| Global by default | No provider necessary. Same key => shared state.
|
|
204
|
-
| Scoping | Wrap with `SharedStatesProvider` to isolate. Nearest provider wins.
|
|
205
|
-
| Named scopes | `scopeName` prop lets distant providers sync (same name ⇒ same bucket). Unnamed providers auto‑generate a random isolated name.
|
|
206
|
-
| Manual override | Third param in `useSharedState` / `useSharedFunction` / `useSharedSubscription` enforces a specific scope ignoring tree search.
|
|
207
|
-
| Shared functions | Encapsulate async logic: single flight + cached result + `error` + `isLoading` + opt‑in refresh.
|
|
208
|
-
| Shared subscriptions | Real-time data streams: automatic cleanup + shared connections + `error` + `isLoading` + subscription state.
|
|
209
|
-
| Static APIs | Access state/functions/subscriptions outside components (`sharedStatesApi`, `sharedFunctionsApi`, `sharedSubscriptionsApi`).
|
|
210
|
-
| Static/shared creation | Use `createSharedState`, `createSharedFunction`, `createSharedSubscription` to export reusable, type-safe shared resources.
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
##
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
199
|
+
## Core Concepts
|
|
200
|
+
| Concept | Summary |
|
|
201
|
+
|------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
202
|
+
| Global by default | No provider necessary. Same key => shared state. |
|
|
203
|
+
| Scoping | Wrap with `SharedStatesProvider` to isolate. Nearest provider wins. |
|
|
204
|
+
| Named scopes | `scopeName` prop lets distant providers sync (same name ⇒ same bucket). Unnamed providers auto‑generate a random isolated name. |
|
|
205
|
+
| Manual override | Third param in `useSharedState` / `useSharedFunction` / `useSharedSubscription` enforces a specific scope ignoring tree search. |
|
|
206
|
+
| Shared functions | Encapsulate async logic: single flight + cached result + `error` + `isLoading` + opt‑in refresh. |
|
|
207
|
+
| Shared subscriptions | Real-time data streams: automatic cleanup + shared connections + `error` + `isLoading` + subscription state. |
|
|
208
|
+
| Static APIs | Access state/functions/subscriptions outside components (`sharedStatesApi`, `sharedFunctionsApi`, `sharedSubscriptionsApi`). |
|
|
209
|
+
| Static/shared creation | Use `createSharedState`, `createSharedFunction`, `createSharedSubscription` to export reusable, type-safe shared resources that persist across `clearAll()` calls. |
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
## Selecting State Slices (`useSharedStateSelector`)
|
|
213
|
+
|
|
214
|
+
When a shared state holds an object, you might only need a small piece of it.
|
|
215
|
+
Using `useSharedState` will cause your component to re-render whenever *any* part of the object changes.
|
|
216
|
+
To optimize performance and avoid unnecessary re-renders, you can use the `useSharedStateSelector` hook.
|
|
217
|
+
|
|
218
|
+
This hook allows you to subscribe to a specific, memoized slice of a shared state.
|
|
219
|
+
Your component will only re-render if the selected value changes.
|
|
220
|
+
It uses `react-fast-compare` for efficient deep equality checks.
|
|
221
|
+
|
|
222
|
+
Signature:
|
|
223
|
+
- `const selectedValue = useSharedStateSelector(key, selector, scopeName?)`
|
|
224
|
+
- `const selectedValue = useSharedStateSelector(sharedStateCreated, selector)`
|
|
225
|
+
|
|
226
|
+
The `selector` is a function that receives the full state and returns the desired slice.
|
|
227
|
+
|
|
228
|
+
### Example: Subscribing to a slice of a user object
|
|
229
|
+
|
|
230
|
+
Imagine a shared state for user settings:
|
|
231
|
+
|
|
232
|
+
```tsx
|
|
233
|
+
// settingsState.ts
|
|
234
|
+
import { createSharedState } from 'react-shared-states';
|
|
235
|
+
|
|
236
|
+
export const settingsState = createSharedState({
|
|
237
|
+
theme: 'dark',
|
|
238
|
+
notifications: {
|
|
239
|
+
email: true,
|
|
240
|
+
push: false,
|
|
241
|
+
},
|
|
242
|
+
language: 'en',
|
|
243
|
+
});
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
A component that only cares about the theme can use `useSharedStateSelector` to avoid re-rendering when, for example, the notification settings change.
|
|
247
|
+
|
|
248
|
+
```tsx
|
|
249
|
+
import { useSharedState, useSharedStateSelector } from 'react-shared-states';
|
|
250
|
+
import { settingsState } from './settingsState';
|
|
251
|
+
|
|
252
|
+
function ThemeDisplay() {
|
|
253
|
+
const theme = useSharedStateSelector(settingsState, (settings) => settings.theme);
|
|
254
|
+
|
|
255
|
+
console.log('ThemeDisplay renders'); // This will only log when the theme changes
|
|
256
|
+
|
|
257
|
+
return <div>Current theme: {theme}</div>;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function NotificationToggle() {
|
|
261
|
+
const [settings, setSettings] = useSharedState(settingsState);
|
|
262
|
+
|
|
263
|
+
const togglePush = () => {
|
|
264
|
+
setSettings(s => ({
|
|
265
|
+
...s,
|
|
266
|
+
notifications: { ...s.notifications, push: !s.notifications.push }
|
|
267
|
+
}));
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
return <button onClick={togglePush}>Toggle Push Notifications</button>;
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
In this example, clicking the `NotificationToggle` button will **not** cause `ThemeDisplay` to re-render.
|
|
275
|
+
|
|
276
|
+
### A Note on Type Safety
|
|
277
|
+
|
|
278
|
+
For the best developer experience and full type safety,
|
|
279
|
+
it is **highly recommended** to use `useSharedStateSelector` with a statically created shared state object from `createSharedState`.
|
|
280
|
+
|
|
281
|
+
When you use a string key directly, the hook cannot infer the type of the state object.
|
|
282
|
+
You would have to provide the types explicitly as generic arguments, or they will default to `any`.
|
|
283
|
+
|
|
284
|
+
```tsx
|
|
285
|
+
// Less safe: using a string key
|
|
286
|
+
// You have to specify the types manually.
|
|
287
|
+
const theme = useSharedStateSelector<{ theme: string; /*...other props*/ }, 'settings', string>(
|
|
288
|
+
'settings',
|
|
289
|
+
(settings) => settings.theme
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
// Recommended: using a created state object
|
|
293
|
+
// Types are inferred automatically!
|
|
294
|
+
const theme = useSharedStateSelector(settingsState, (settings) => settings.theme);
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Shared Async Functions (`useSharedFunction`)
|
|
260
298
|
Signature:
|
|
261
299
|
- `const { state, trigger, forceTrigger, clear } = useSharedFunction(key, asyncFn, scopeName?)`
|
|
262
300
|
- `const { state, trigger, forceTrigger, clear } = useSharedFunction(sharedFunctionCreated)`
|
|
@@ -267,6 +305,7 @@ Semantics:
|
|
|
267
305
|
* Multiple components with the same key+scope share one execution + result.
|
|
268
306
|
* `clear()` deletes the cache (next trigger re-runs).
|
|
269
307
|
* You decide when to invoke `trigger` (e.g. on mount, on button click, when dependencies change, etc.).
|
|
308
|
+
* Functions created with `createSharedFunction` are **static** and persist across `clearAll()` calls.
|
|
270
309
|
|
|
271
310
|
### Pattern: lazy load on first render
|
|
272
311
|
```tsx
|
|
@@ -286,7 +325,7 @@ const refresh = () => forceTrigger();
|
|
|
286
325
|
```
|
|
287
326
|
|
|
288
327
|
|
|
289
|
-
##
|
|
328
|
+
## Real-time Subscriptions (`useSharedSubscription`)
|
|
290
329
|
Perfect for Firebase listeners, WebSocket connections,
|
|
291
330
|
Server-Sent Events, or any streaming data source that needs cleanup.
|
|
292
331
|
|
|
@@ -298,8 +337,8 @@ Signature:
|
|
|
298
337
|
|
|
299
338
|
The `subscriber` function receives three callbacks:
|
|
300
339
|
- `set(data)`: Update the shared data
|
|
301
|
-
- `
|
|
302
|
-
- `
|
|
340
|
+
- `error(error)`: Handle errors
|
|
341
|
+
- `complete()`: Mark loading as complete
|
|
303
342
|
- Returns: Optional cleanup function (called on unsubscribe/unmount)
|
|
304
343
|
|
|
305
344
|
### Pattern: Firebase Firestore real-time listener
|
|
@@ -310,8 +349,23 @@ import { createSharedSubscription } from 'react-shared-states';
|
|
|
310
349
|
import { db } from './firebase-config';
|
|
311
350
|
|
|
312
351
|
export const userSubscription = createSharedSubscription(
|
|
313
|
-
|
|
314
|
-
|
|
352
|
+
(set, error, complete) => {
|
|
353
|
+
const userDocRef = doc(db, 'users', 'some-user-id');
|
|
354
|
+
const unsubscribe = onSnapshot(userDocRef,
|
|
355
|
+
(doc) => {
|
|
356
|
+
if (doc.exists()) {
|
|
357
|
+
set(doc.data());
|
|
358
|
+
} else {
|
|
359
|
+
error(new Error('User not found'));
|
|
360
|
+
}
|
|
361
|
+
complete();
|
|
362
|
+
},
|
|
363
|
+
(err) => {
|
|
364
|
+
error(err);
|
|
365
|
+
complete();
|
|
366
|
+
}
|
|
367
|
+
);
|
|
368
|
+
return unsubscribe;
|
|
315
369
|
}
|
|
316
370
|
);
|
|
317
371
|
|
|
@@ -344,15 +398,15 @@ import { useSharedSubscription } from 'react-shared-states';
|
|
|
344
398
|
function ChatRoom({ roomId }: { roomId: string }) {
|
|
345
399
|
const { state, trigger } = useSharedSubscription(
|
|
346
400
|
`chat-${roomId}`,
|
|
347
|
-
(set,
|
|
401
|
+
(set, error, complete) => {
|
|
348
402
|
const ws = new WebSocket(`ws://chat-server/${roomId}`);
|
|
349
403
|
|
|
350
|
-
ws.onopen = () =>
|
|
404
|
+
ws.onopen = () => complete();
|
|
351
405
|
ws.onmessage = (event) => {
|
|
352
406
|
const message = JSON.parse(event.data);
|
|
353
407
|
set(prev => [...(prev || []), message]);
|
|
354
408
|
};
|
|
355
|
-
ws.onerror =
|
|
409
|
+
ws.onerror = error;
|
|
356
410
|
|
|
357
411
|
return () => ws.close();
|
|
358
412
|
}
|
|
@@ -384,14 +438,14 @@ import { useSharedSubscription } from 'react-shared-states';
|
|
|
384
438
|
function LiveUpdates() {
|
|
385
439
|
const { state, trigger } = useSharedSubscription(
|
|
386
440
|
'live-updates',
|
|
387
|
-
(set,
|
|
441
|
+
(set, error, complete) => {
|
|
388
442
|
const eventSource = new EventSource('/api/live-updates');
|
|
389
443
|
|
|
390
|
-
eventSource.onopen = () =>
|
|
444
|
+
eventSource.onopen = () => complete();
|
|
391
445
|
eventSource.onmessage = (event) => {
|
|
392
446
|
set(JSON.parse(event.data));
|
|
393
447
|
};
|
|
394
|
-
eventSource.onerror =
|
|
448
|
+
eventSource.onerror = error;
|
|
395
449
|
|
|
396
450
|
return () => eventSource.close();
|
|
397
451
|
}
|
|
@@ -413,10 +467,12 @@ Subscription semantics:
|
|
|
413
467
|
* Components mounting later instantly get the latest `data` without re-subscribing.
|
|
414
468
|
|
|
415
469
|
|
|
416
|
-
##
|
|
417
|
-
##
|
|
470
|
+
## Static APIs (outside React)
|
|
471
|
+
## Static/Global Shared Resource Creation
|
|
418
472
|
|
|
419
|
-
For large apps, you can create and export shared state, function,
|
|
473
|
+
For large apps, you can create and export shared state, function,
|
|
474
|
+
or subscription objects for type safety and to avoid key collisions.
|
|
475
|
+
This pattern is similar to Zustand or Jotai stores:
|
|
420
476
|
|
|
421
477
|
```ts
|
|
422
478
|
import { createSharedState, createSharedFunction, createSharedSubscription, useSharedState, useSharedFunction, useSharedSubscription } from 'react-shared-states';
|
|
@@ -424,7 +480,7 @@ import { createSharedState, createSharedFunction, createSharedSubscription, useS
|
|
|
424
480
|
// Create and export shared resources
|
|
425
481
|
export const counterState = createSharedState(0);
|
|
426
482
|
export const fetchUserFunction = createSharedFunction(() => fetch('/api/me').then(r => r.json()));
|
|
427
|
-
export const chatSubscription = createSharedSubscription((set,
|
|
483
|
+
export const chatSubscription = createSharedSubscription((set, error, complete) => {/* ... */});
|
|
428
484
|
|
|
429
485
|
// Use anywhere in your app
|
|
430
486
|
const [count, setCount] = useSharedState(counterState);
|
|
@@ -463,16 +519,16 @@ const subStateScoped = sharedSubscriptionsApi.get('live-chat', 'myScope');
|
|
|
463
519
|
|
|
464
520
|
## API summary:
|
|
465
521
|
|
|
466
|
-
| API | Methods
|
|
467
|
-
|
|
468
|
-
| `sharedStatesApi` | `get(key, scopeName?)`, `set(key, val, scopeName?)`, `has(key, scopeName?)`, `clear(key, scopeName?)`, `clearAll()`, `clearScope(scopeName?)`, `getAll()` |
|
|
469
|
-
| `sharedFunctionsApi` | `get(key, scopeName?)`, `set(key, val, scopeName?)`, `has(key, scopeName?)`, `clear(key, scopeName?)`, `clearAll()`, `clearScope(scopeName?)`, `getAll()` |
|
|
470
|
-
| `sharedSubscriptionsApi` | `get(key, scopeName?)`, `set(key, val, scopeName?)`, `has(key, scopeName?)`, `clear(key, scopeName?)`, `clearAll()`, `clearScope(scopeName?)`, `getAll()` |
|
|
522
|
+
| API | Methods |
|
|
523
|
+
|--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
524
|
+
| `sharedStatesApi` | `get(key, scopeName?)`, `set(key, val, scopeName?)`, `has(key, scopeName?)`, `clear(key, scopeName?)`, `clearAll(withoutListeners?, withStatic?)`, `clearScope(scopeName?)`, `getAll()` |
|
|
525
|
+
| `sharedFunctionsApi` | `get(key, scopeName?)`, `set(key, val, scopeName?)`, `has(key, scopeName?)`, `clear(key, scopeName?)`, `clearAll(withoutListeners?, withStatic?)`, `clearScope(scopeName?)`, `getAll()` |
|
|
526
|
+
| `sharedSubscriptionsApi` | `get(key, scopeName?)`, `set(key, val, scopeName?)`, `has(key, scopeName?)`, `clear(key, scopeName?)`, `clearAll(withoutListeners?, withStatic?)`, `clearScope(scopeName?)`, `getAll()` |
|
|
471
527
|
|
|
472
528
|
`scopeName` defaults to `"_global"`. Internally, keys are stored as `${scope}//${key}`. The `.getAll()` method returns a nested object: `{ [scope]: { [key]: value } }`.
|
|
473
529
|
|
|
474
530
|
|
|
475
|
-
##
|
|
531
|
+
## Scoping Rules Deep Dive
|
|
476
532
|
Resolution order used inside hooks:
|
|
477
533
|
1. Explicit 3rd parameter (`scopeName`)
|
|
478
534
|
2. Nearest `SharedStatesProvider` above the component
|
|
@@ -483,7 +539,7 @@ Unnamed providers auto‑generate a random scope name: each mount = isolated isl
|
|
|
483
539
|
Two providers sharing the same `scopeName` act as a single logical scope even if they are disjoint in the tree (great for portals / microfrontends).
|
|
484
540
|
|
|
485
541
|
|
|
486
|
-
##
|
|
542
|
+
## Comparison Snapshot
|
|
487
543
|
| Criterion | react-shared-states | Redux Toolkit | Zustand |
|
|
488
544
|
|----------------|------------------------------------------|----------------------|----------------------------------|
|
|
489
545
|
| Setup | Install & call hook | Slice + store config | Create store function |
|
|
@@ -495,16 +551,16 @@ Two providers sharing the same `scopeName` act as a single logical scope even if
|
|
|
495
551
|
| Learning curve | Minutes | Higher | Low |
|
|
496
552
|
|
|
497
553
|
|
|
498
|
-
##
|
|
554
|
+
## Testing Tips
|
|
499
555
|
* Use static APIs to assert state after component interactions.
|
|
500
|
-
* `sharedStatesApi.clearAll()`, `sharedFunctionsApi.clearAll()`, `sharedSubscriptionsApi.clearAll()` in `afterEach` to isolate tests.
|
|
556
|
+
* `sharedStatesApi.clearAll(false, true)`, `sharedFunctionsApi.clearAll(false, true)`, `sharedSubscriptionsApi.clearAll(false, true)` in `afterEach` to isolate tests and clear static states.
|
|
501
557
|
* For async functions: trigger once, await UI stabilization, assert `results` present.
|
|
502
558
|
* For subscriptions: mock the subscription source (Firebase, WebSocket, etc.) and verify data flow.
|
|
503
559
|
|
|
504
560
|
|
|
505
561
|
## ❓ FAQ
|
|
506
562
|
**Q: How do I reset a single shared state?**
|
|
507
|
-
`sharedStatesApi.clear('key')
|
|
563
|
+
`sharedStatesApi.clear('key')`. If the state was created with `createSharedState`, it will reset to its initial value. Otherwise, it will be removed.
|
|
508
564
|
|
|
509
565
|
**Q: Can I pre-hydrate data on the server?**
|
|
510
566
|
Yes. Call `sharedStatesApi.set(...)` during bootstrap, then first client hook usage will pick it up.
|
|
@@ -522,13 +578,19 @@ Subscriptions auto-cleanup when no components are listening. You can also manual
|
|
|
522
578
|
Currently no built-in Suspense wrappers; wrap `useSharedFunction` yourself if desired.
|
|
523
579
|
|
|
524
580
|
|
|
525
|
-
##
|
|
581
|
+
## Full API Reference
|
|
526
582
|
### `useSharedState(key, initialValue, scopeName?)`
|
|
527
583
|
Returns `[value, setValue]`.
|
|
528
584
|
|
|
529
585
|
### `useSharedState(sharedStateCreated)`
|
|
530
586
|
Returns `[value, setValue]`.
|
|
531
587
|
|
|
588
|
+
### `useSharedStateSelector(key, selector, scopeName?)`
|
|
589
|
+
Returns the selected value.
|
|
590
|
+
|
|
591
|
+
### `useSharedStateSelector(sharedStateCreated, selector)`
|
|
592
|
+
Returns the selected value.
|
|
593
|
+
|
|
532
594
|
### `useSharedFunction(key, fn, scopeName?)`
|
|
533
595
|
Returns `{ state, trigger, forceTrigger, clear }`.
|
|
534
596
|
|
|
@@ -549,7 +611,7 @@ Wrap children; optional `scopeName` (string). If omitted a random unique one is
|
|
|
549
611
|
|
|
550
612
|
|
|
551
613
|
|
|
552
|
-
##
|
|
614
|
+
## Contributions
|
|
553
615
|
|
|
554
616
|
We welcome contributions!
|
|
555
617
|
If you'd like to improve `react-shared-states`,
|
|
@@ -567,4 +629,6 @@ feel free to [open an issue](https://github.com/HichemTab-tech/react-shared-stat
|
|
|
567
629
|
## 🌟 Acknowledgements
|
|
568
630
|
|
|
569
631
|
Inspired by React's built-in primitives and the ergonomics of modern lightweight state libraries.
|
|
570
|
-
Thanks to early adopters for feedback.
|
|
632
|
+
Thanks to early adopters for feedback.
|
|
633
|
+
If you'd like to improve `react-shared-states`,
|
|
634
|
+
feel free to [open an issue](https://github.com/HichemTab-tech/react-shared-states/issues) or [submit a pull request](https://github.com/HichemTab-tech/react-shared-states/pulls).
|
|
@@ -1,37 +1,44 @@
|
|
|
1
|
-
import { AFunction,
|
|
2
|
-
|
|
3
|
-
export declare abstract class
|
|
4
|
-
data: Map<string,
|
|
5
|
-
defaultValue():
|
|
1
|
+
import { AFunction, Prefix, SharedCreated, SharedValue } from './types';
|
|
2
|
+
export declare const staticStores: SharedCreated[];
|
|
3
|
+
export declare abstract class SharedValuesManager<T extends SharedValue, V> {
|
|
4
|
+
data: Map<string, T>;
|
|
5
|
+
defaultValue(): V;
|
|
6
6
|
addListener(key: string, prefix: Prefix, listener: AFunction): void;
|
|
7
7
|
removeListener(key: string, prefix: Prefix, listener: AFunction): void;
|
|
8
8
|
callListeners(key: string, prefix: Prefix): void;
|
|
9
|
-
init(key: string, prefix: Prefix, data:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
init(key: string, prefix: Prefix, data: V, isStatic?: boolean): void;
|
|
10
|
+
createStatic<X extends SharedCreated>(rest: Omit<X, 'key' | 'prefix'>, scopeName?: Prefix): {
|
|
11
|
+
key: string;
|
|
12
|
+
prefix: Prefix;
|
|
13
|
+
} & Omit<X, "key" | "prefix">;
|
|
14
|
+
initStatic(sharedCreated: SharedCreated): void;
|
|
15
|
+
clearAll(withoutListeners?: boolean, withStatic?: boolean): void;
|
|
16
|
+
clear(key: string, prefix: Prefix, withoutListeners?: boolean, withStatic?: boolean): void;
|
|
17
|
+
get(key: string, prefix: Prefix): T | undefined;
|
|
18
|
+
setValue(key: string, prefix: Prefix, data: V): void;
|
|
14
19
|
has(key: string, prefix: Prefix): string | undefined;
|
|
15
20
|
static prefix(key: string, prefix: Prefix): string;
|
|
16
21
|
static extractPrefix(mapKey: string): string[];
|
|
17
22
|
useEffect(key: string, prefix: Prefix, unsub?: (() => void) | null): void;
|
|
18
23
|
}
|
|
19
|
-
export declare class
|
|
20
|
-
|
|
21
|
-
constructor(sharedData:
|
|
24
|
+
export declare class SharedValuesApi<T extends SharedValue, V, R = T> {
|
|
25
|
+
protected sharedData: SharedValuesManager<T, V>;
|
|
26
|
+
constructor(sharedData: SharedValuesManager<T, V>);
|
|
22
27
|
/**
|
|
23
28
|
* get a value from the shared data
|
|
24
29
|
* @param key
|
|
25
30
|
* @param scopeName
|
|
26
31
|
*/
|
|
27
|
-
get<S extends string = string>(key: S, scopeName: Prefix):
|
|
32
|
+
get<S extends string = string>(key: S, scopeName: Prefix): R;
|
|
33
|
+
get<S extends string = string>(sharedCreated: SharedCreated): R;
|
|
28
34
|
/**
|
|
29
35
|
* set a value in the shared data
|
|
30
36
|
* @param key
|
|
31
37
|
* @param value
|
|
32
38
|
* @param scopeName
|
|
33
39
|
*/
|
|
34
|
-
set<S extends string = string>(key: S, value:
|
|
40
|
+
set<S extends string = string>(key: S, value: V, scopeName: Prefix): void;
|
|
41
|
+
set<S extends string = string>(sharedCreated: SharedCreated, value: V): void;
|
|
35
42
|
/**
|
|
36
43
|
* clear all values from the shared data
|
|
37
44
|
*/
|
|
@@ -45,7 +52,12 @@ export declare class SharedApi<T> {
|
|
|
45
52
|
* resolve a shared created object to a value
|
|
46
53
|
* @param sharedCreated
|
|
47
54
|
*/
|
|
48
|
-
resolve(sharedCreated: SharedCreated):
|
|
55
|
+
resolve(sharedCreated: SharedCreated): R;
|
|
56
|
+
/**
|
|
57
|
+
* clear a value from the shared data
|
|
58
|
+
* @param key
|
|
59
|
+
* @param scopeName
|
|
60
|
+
*/
|
|
49
61
|
clear(key: string, scopeName: Prefix): void;
|
|
50
62
|
clear(sharedCreated: SharedCreated): void;
|
|
51
63
|
/**
|
|
@@ -59,4 +71,3 @@ export declare class SharedApi<T> {
|
|
|
59
71
|
*/
|
|
60
72
|
getAll(): Record<string, Record<string, any>>;
|
|
61
73
|
}
|
|
62
|
-
export {};
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { useSharedState, sharedStatesApi, createSharedState, SharedStatesApi } from './use-shared-state';
|
|
2
|
-
export type { SharedStateCreated } from './use-shared-state';
|
|
1
|
+
export { useSharedState, sharedStatesApi, createSharedState, SharedStatesApi, useSharedStateSelector } from './use-shared-state';
|
|
2
|
+
export type { SharedStateCreated, SharedStateSelector } from './use-shared-state';
|
|
3
3
|
export { useSharedFunction, sharedFunctionsApi, createSharedFunction, SharedFunctionsApi } from './use-shared-function';
|
|
4
4
|
export type { SharedFunctionStateReturn } from './use-shared-function';
|
|
5
5
|
export { useSharedSubscription, sharedSubscriptionsApi, createSharedSubscription, SharedSubscriptionsApi } from './use-shared-subscription';
|
|
@@ -1,15 +1,40 @@
|
|
|
1
|
-
import { AFunction, Prefix, SharedCreated } from '../types';
|
|
2
|
-
import {
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
error?: unknown;
|
|
8
|
-
};
|
|
1
|
+
import { AFunction, Prefix, SharedCreated, SharedValue } from '../types';
|
|
2
|
+
import { SharedValuesApi, SharedValuesManager } from '../SharedValuesManager';
|
|
3
|
+
type SharedFunctionValue<T> = {
|
|
4
|
+
results?: T;
|
|
5
|
+
isLoading: boolean;
|
|
6
|
+
error?: unknown;
|
|
9
7
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
interface SharedFunction<T> extends SharedValue {
|
|
9
|
+
fnState: SharedFunctionValue<T>;
|
|
10
|
+
}
|
|
11
|
+
declare class SharedFunctionsManager extends SharedValuesManager<SharedFunction<unknown>, {
|
|
12
|
+
fnState: SharedFunctionValue<unknown>;
|
|
13
|
+
}> {
|
|
14
|
+
defaultValue(): {
|
|
15
|
+
fnState: {
|
|
16
|
+
results: undefined;
|
|
17
|
+
isLoading: boolean;
|
|
18
|
+
error: undefined;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
initValue(key: string, prefix: Prefix, isStatic?: boolean): void;
|
|
22
|
+
setValue<T>(key: string, prefix: Prefix, data: {
|
|
23
|
+
fnState: SharedFunctionValue<T>;
|
|
24
|
+
}): void;
|
|
25
|
+
}
|
|
26
|
+
export declare class SharedFunctionsApi extends SharedValuesApi<SharedFunction<unknown>, {
|
|
27
|
+
fnState: SharedFunctionValue<unknown>;
|
|
28
|
+
}, SharedFunctionValue<unknown>> {
|
|
29
|
+
constructor(sharedFunctionManager: SharedFunctionsManager);
|
|
30
|
+
get<T, S extends string = string>(key: S, scopeName?: Prefix): SharedFunctionValue<T>;
|
|
31
|
+
get<T, Args extends unknown[]>(sharedFunctionCreated: SharedFunctionCreated<T, Args>): SharedFunctionValue<T>;
|
|
32
|
+
set<T, S extends string = string>(key: S, value: {
|
|
33
|
+
fnState: SharedFunctionValue<T>;
|
|
34
|
+
}, scopeName?: Prefix): void;
|
|
35
|
+
set<T, Args extends unknown[]>(sharedFunctionCreated: SharedFunctionCreated<T, Args>, value: {
|
|
36
|
+
fnState: SharedFunctionValue<T>;
|
|
37
|
+
}): void;
|
|
13
38
|
}
|
|
14
39
|
export declare const sharedFunctionsApi: SharedFunctionsApi;
|
|
15
40
|
interface SharedFunctionCreated<T, Args extends unknown[]> extends SharedCreated {
|
|
@@ -17,7 +42,7 @@ interface SharedFunctionCreated<T, Args extends unknown[]> extends SharedCreated
|
|
|
17
42
|
}
|
|
18
43
|
export declare const createSharedFunction: <T, Args extends unknown[]>(fn: AFunction<T, Args>, scopeName?: Prefix) => SharedFunctionCreated<T, Args>;
|
|
19
44
|
export type SharedFunctionStateReturn<T, Args extends unknown[]> = {
|
|
20
|
-
readonly state: NonNullable<
|
|
45
|
+
readonly state: NonNullable<SharedFunctionValue<T>>;
|
|
21
46
|
readonly trigger: (...args: Args) => void;
|
|
22
47
|
readonly forceTrigger: (...args: Args) => void;
|
|
23
48
|
readonly clear: () => void;
|
|
@@ -1,10 +1,25 @@
|
|
|
1
|
-
import { Prefix, SharedCreated } from '../types';
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import { Prefix, SharedCreated, SharedValue } from '../types';
|
|
2
|
+
import { SharedValuesApi, SharedValuesManager } from '../SharedValuesManager';
|
|
3
|
+
interface SharedState<T> extends SharedValue {
|
|
4
|
+
value: T;
|
|
5
|
+
}
|
|
6
|
+
declare class SharedStatesManager extends SharedValuesManager<SharedState<unknown>, {
|
|
4
7
|
value: unknown;
|
|
5
8
|
}> {
|
|
9
|
+
defaultValue(): {
|
|
10
|
+
value: undefined;
|
|
11
|
+
};
|
|
12
|
+
initValue(key: string, prefix: Prefix, value: unknown, isStatic?: boolean): void;
|
|
13
|
+
initStatic(sharedStateCreated: SharedStateCreated<any>): void;
|
|
14
|
+
}
|
|
15
|
+
export declare class SharedStatesApi extends SharedValuesApi<SharedState<unknown>, {
|
|
16
|
+
value: unknown;
|
|
17
|
+
}, unknown> {
|
|
18
|
+
constructor(sharedStateManager: SharedStatesManager);
|
|
6
19
|
get<T, S extends string = string>(key: S, scopeName?: Prefix): T;
|
|
20
|
+
get<T>(sharedStateCreated: SharedStateCreated<T>): T;
|
|
7
21
|
set<T, S extends string = string>(key: S, value: T, scopeName?: Prefix): void;
|
|
22
|
+
set<T>(sharedStateCreated: SharedStateCreated<T>, value: T): void;
|
|
8
23
|
}
|
|
9
24
|
export declare const sharedStatesApi: SharedStatesApi;
|
|
10
25
|
export interface SharedStateCreated<T> extends SharedCreated {
|
|
@@ -13,3 +28,7 @@ export interface SharedStateCreated<T> extends SharedCreated {
|
|
|
13
28
|
export declare const createSharedState: <T>(initialValue: T, scopeName?: Prefix) => SharedStateCreated<T>;
|
|
14
29
|
export declare function useSharedState<T, S extends string>(key: S, initialValue: T, scopeName?: Prefix): readonly [T, (v: T | ((prev: T) => T)) => void];
|
|
15
30
|
export declare function useSharedState<T>(sharedStateCreated: SharedStateCreated<T>): readonly [T, (v: T | ((prev: T) => T)) => void];
|
|
31
|
+
export type SharedStateSelector<S, T = S> = (original: S) => T;
|
|
32
|
+
export declare function useSharedStateSelector<T, S extends string, R>(key: S, selector: SharedStateSelector<T, R>, scopeName?: Prefix): Readonly<R>;
|
|
33
|
+
export declare function useSharedStateSelector<T, R>(sharedStateCreated: SharedStateCreated<T>, selector: SharedStateSelector<T, R>): Readonly<R>;
|
|
34
|
+
export {};
|