Skip to content

Commit 926c1f6

Browse files
Merge pull request #26 from HichemTab-tech/add-updaters
Add updaters to apis
2 parents bb4e5a0 + 83d832a commit 926c1f6

File tree

7 files changed

+131
-6
lines changed

7 files changed

+131
-6
lines changed

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -519,11 +519,11 @@ const subStateScoped = sharedSubscriptionsApi.get('live-chat', 'myScope');
519519

520520
## API summary:
521521

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()` |
522+
| API | Methods |
523+
|--------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
524+
| `sharedStatesApi` | `get(key, scopeName?)`, `set(key, val, scopeName?)`, `update(key, updater, scopeName?)`, `has(key, scopeName?)`, `clear(key, scopeName?)`, `clearAll(withoutListeners?, withStatic?)`, `clearScope(scopeName?)`, `getAll()` |
525+
| `sharedFunctionsApi` | `get(key, scopeName?)`, `set(key, val, scopeName?)`, `update(key, updater, scopeName?)`, `has(key, scopeName?)`, `clear(key, scopeName?)`, `clearAll(withoutListeners?, withStatic?)`, `clearScope(scopeName?)`, `getAll()` |
526+
| `sharedSubscriptionsApi` | `get(key, scopeName?)`, `set(key, val, scopeName?)`, `update(key, updater, scopeName?)`, `has(key, scopeName?)`, `clear(key, scopeName?)`, `clearAll(withoutListeners?, withStatic?)`, `clearScope(scopeName?)`, `getAll()` |
527527

528528
`scopeName` defaults to `"_global"`. Internally, keys are stored as `${scope}//${key}`. The `.getAll()` method returns a nested object: `{ [scope]: { [key]: value } }`.
529529

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-shared-states",
3-
"version": "1.0.13",
3+
"version": "1.0.14",
44
"type": "module",
55
"description": "Global state made as simple as useState, with zero config, built-in async caching, and automatic scoping.",
66
"keywords": [

src/SharedValuesManager.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,33 @@ export class SharedValuesApi<T extends SharedValue, V, R = T> {
180180
this.sharedData.callListeners(keyStr, prefix);
181181
}
182182

183+
/**
184+
* update a value in the shared data
185+
* @param key
186+
* @param updater
187+
* @param scopeName
188+
*/
189+
update<S extends string = string>(key: S, updater: (prev: R) => V, scopeName: Prefix): void;
190+
update<S extends string = string>(sharedCreated: SharedCreated, updater: (prev: R) => V): void;
191+
update<S extends string = string>(key: S | SharedCreated, updater: (prev: R) => V, scopeName?: Prefix) {
192+
193+
let prevData;
194+
if (typeof key === "string") {
195+
prevData = this.get<S>(key, scopeName as Prefix);
196+
}
197+
else{
198+
prevData = this.get(key);
199+
}
200+
const newValue = updater(prevData);
201+
202+
if (typeof key === "string") {
203+
this.set(key, newValue, scopeName as Prefix);
204+
}
205+
else{
206+
this.set(key, newValue);
207+
}
208+
}
209+
183210
/**
184211
* clear all values from the shared data
185212
*/

src/hooks/use-shared-function.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,22 @@ export class SharedFunctionsApi extends SharedValuesApi<SharedFunction<unknown>,
5555
}
5656
super.set(key, value, scopeName);
5757
}
58+
update<T, Args extends unknown[], S extends string = string>(key: S, updater: (prev: SharedFunctionValue<T>) => { fnState: SharedFunctionValue<T> }, scopeName?: Prefix): void;
59+
update<T, Args extends unknown[]>(sharedFunctionCreated: SharedFunctionCreated<T, Args>, updater: (prev: SharedFunctionValue<T>) => { fnState: SharedFunctionValue<T> }): void;
60+
update<T, Args extends unknown[], S extends string = string>(key: S | SharedFunctionCreated<T, Args>, updater: (prev: SharedFunctionValue<T>) => { fnState: SharedFunctionValue<T> }, scopeName: Prefix = "_global") {
61+
let prev: SharedFunctionValue<T>;
62+
if (typeof key === "string") {
63+
prev = this.get(key, scopeName);
64+
} else {
65+
prev = this.get(key);
66+
}
67+
const newValue = updater(prev);
68+
if (typeof key === "string") {
69+
this.set(key, newValue, scopeName);
70+
} else {
71+
this.set(key, newValue);
72+
}
73+
}
5874
}
5975

6076
const sharedFunctionsManager = new SharedFunctionsManager();

src/hooks/use-shared-state.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,22 @@ export class SharedStatesApi extends SharedValuesApi<SharedState<unknown>, { val
4747
}
4848
super.set(key, {value}, scopeName);
4949
}
50+
update<T, S extends string = string>(key: S, updater: (prev: T) => T, scopeName?: Prefix): void;
51+
update<T>(sharedStateCreated: SharedStateCreated<T>, updater: (prev: T) => T): void;
52+
update<T, S extends string = string>(key: S | SharedStateCreated<T>, updater: (prev: T) => T, scopeName: Prefix = "_global") {
53+
let prev: T;
54+
if (typeof key === "string") {
55+
prev = this.get(key, scopeName);
56+
} else {
57+
prev = this.get(key);
58+
}
59+
const newValue = updater(prev);
60+
if (typeof key === "string") {
61+
this.set(key, newValue, scopeName);
62+
} else {
63+
this.set(key, newValue);
64+
}
65+
}
5066
}
5167

5268
const sharedStatesManager = new SharedStatesManager();

src/hooks/use-shared-subscription.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,22 @@ export class SharedSubscriptionsApi extends SharedValuesApi<SharedSubscription<u
9292
}
9393
super.set(key, value, scopeName);
9494
}
95+
update<T, S extends string = string>(key: S, updater: (prev: SharedSubscriptionValue<T>) => { fnState: SharedSubscriptionValue<T> }, scopeName?: Prefix): void;
96+
update<T>(sharedSubscriptionCreated: SharedSubscriptionCreated<T>, updater: (prev: SharedSubscriptionValue<T>) => { fnState: SharedSubscriptionValue<T> }): void;
97+
update<T, S extends string = string>(key: S | SharedSubscriptionCreated<T>, updater: (prev: SharedSubscriptionValue<T>) => { fnState: SharedSubscriptionValue<T> }, scopeName: Prefix = "_global") {
98+
let prev: SharedSubscriptionValue<T>;
99+
if (typeof key === "string") {
100+
prev = this.get(key, scopeName);
101+
} else {
102+
prev = this.get(key);
103+
}
104+
const newValue = updater(prev);
105+
if (typeof key === "string") {
106+
this.set(key, newValue, scopeName);
107+
} else {
108+
this.set(key, newValue);
109+
}
110+
}
95111
}
96112

97113
const sharedSubscriptionsManager = new SharedSubscriptionsManager();

tests/index.test.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,14 @@ describe('useSharedState', () => {
159159
// Get updated value
160160
expect(sharedStatesApi.get(sharedCounter)).toBe(200);
161161

162+
// Update the value
163+
act(() => {
164+
sharedStatesApi.update(sharedCounter, (prev) => prev + 50);
165+
});
166+
167+
// Get updated value after update
168+
expect(sharedStatesApi.get(sharedCounter)).toBe(250);
169+
162170
// Clear the value
163171
act(() => {
164172
sharedStatesApi.clear(sharedCounter);
@@ -310,6 +318,20 @@ describe('useSharedFunction', () => {
310318
expect(updatedState.isLoading).toBe(true);
311319
expect(updatedState.error).toBe('test error');
312320

321+
// Update the state
322+
act(() => {
323+
sharedFunctionsApi.update(sharedFunction, (prev) => ({
324+
fnState: {
325+
...prev,
326+
results: 'updated data',
327+
}
328+
}));
329+
});
330+
331+
// Get updated state after update
332+
const updatedState2 = sharedFunctionsApi.get(sharedFunction);
333+
expect(updatedState2.results).toBe('updated data');
334+
313335
// Clear the value
314336
act(() => {
315337
sharedFunctionsApi.clear(sharedFunction);
@@ -374,6 +396,20 @@ describe('useSharedSubscription', () => {
374396
expect(updatedState.isLoading).toBe(true);
375397
expect(updatedState.error).toBe('test error');
376398

399+
// Update the state
400+
act(() => {
401+
sharedSubscriptionsApi.update(sharedSubscription, (prev) => ({
402+
fnState: {
403+
...prev,
404+
data: 'updated data',
405+
}
406+
}));
407+
});
408+
409+
// Get updated state after update
410+
const updatedState2 = sharedSubscriptionsApi.get(sharedSubscription);
411+
expect(updatedState2.data).toBe('updated data');
412+
377413
// Clear the value
378414
act(() => {
379415
sharedSubscriptionsApi.clear(sharedSubscription);
@@ -513,6 +549,20 @@ describe('useSharedSubscription', () => {
513549
expect(updatedState.isLoading).toBe(true);
514550
expect(updatedState.error).toBe('test error');
515551

552+
// Update the state
553+
act(() => {
554+
sharedSubscriptionsApi.update(sharedSubscription, (prev) => ({
555+
fnState: {
556+
...prev,
557+
data: 'updated data',
558+
}
559+
}));
560+
});
561+
562+
// Get updated state after update
563+
const updatedState2 = sharedSubscriptionsApi.get(sharedSubscription);
564+
expect(updatedState2.data).toBe('updated data');
565+
516566
// Clear the value
517567
act(() => {
518568
sharedSubscriptionsApi.clear(sharedSubscription);

0 commit comments

Comments
 (0)