Skip to content

Commit

Permalink
Feat/prop getter improvements (#10)
Browse files Browse the repository at this point in the history
* update files to publish

* updates readme with more examples

* feat: add prop getter improvements

* chore: unused import

* merge resolution issues from vs code, need to switch back to webstorm

* update readme with throtle
  • Loading branch information
JuliusKoronciCH authored Apr 7, 2024
1 parent 8fa1450 commit a769773
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 12 deletions.
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,9 @@ const [count, setCount] = useStoreValue('count');
// Access a property and disable caching
const [profileName, setProfileName] = useStoreValue('profile.name', { disableCache: true });
// Access a property and set frequency of updates
const [profileEmail, setProfileEmail] = useStoreValue('profile.email', { throttle: 100 });
```

By default, useStoreValue maintains local state, ensuring immediate updates without waiting for a roundtrip through the global store. When the store is updated, the value is propagated back to the hook, synchronizing the local state.
Expand All @@ -394,7 +397,7 @@ MIT
- Parameters:
- `initialState`: The initial state object of your store.
- `options`: An optional object containing configuration settings:
- `debug`: Enables debug logging (default: `false`).
- `debug`: Enables debug logging (default: `false`).
- `hydrator`: An asynchronous function returning a promise resolving to the hydration data.
- `persist`: An asynchronous function to handle state persistence.

Expand All @@ -405,7 +408,7 @@ MIT
- `type`: The property path within the store to be updated (e.g., 'count', 'profile.name').
- `payload`: The new value for the specified property.

- `getPropertyObservable<K extends PropertyPath<T>>(eventType: K)`
- `getPropertyObservable<K extends PropertyPath<T>>(eventType: K, throttle?: number)`

- Returns an RxJS Observable that emits values whenever the specified property in the store is updated.

Expand All @@ -422,20 +425,21 @@ MIT
- React hook to access and update a specific property within the store.
- Parameters:
- `type`: The property path within the store.
- `options`: Optional object with a `disableCache` property to control local caching behavior.
- Returns: An array containing:
- `options.disableCache`: boolean property to control local caching behavior.
- `options.throtle`: numeric property to control frequency of updates in ms.
- Returns: An array containing:
- The current value of the property.
- A function to update the property.

- `useHydrateStore()`

- React hook to trigger store hydration.
- Returns: A function to initialize the store with hydrated data.
- Returns: A function to initialize the store with hydrated data.

- `useIsHydrated()`

- React hook to determine if the store is hydrated.
- Returns: A boolean indicating hydration status.
- Returns: A boolean indicating hydration status.

- `systemEvents$`

Expand Down
25 changes: 19 additions & 6 deletions lib/event-store.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { BehaviorSubject, type Observable } from 'rxjs';
import { BehaviorSubject, Subject, type Observable } from 'rxjs';
import {
auditTime,
distinctUntilChanged,
filter,
map,
scan,
share,
startWith,
tap,
} from 'rxjs/operators';
Expand Down Expand Up @@ -46,13 +48,17 @@ export function createEventStore<T extends object>(

const getPropertyObservable = <K extends PropertyPath<T>>(
eventType: K,
throttle?: number,
): Observable<GetValueType<T, K>> => {
return globalEventStore$.pipe(
const observable = globalEventStore$.pipe(
filter((event) => event.type.startsWith(eventType)),
map((event) => event.payload as GetValueType<T, K>),
scan((__, curr) => curr),
distinctUntilChanged(),
share({ connector: () => new Subject(), resetOnRefCountZero: true }),
);
if (throttle) {
observable.pipe(auditTime(throttle));
}
return observable;
};

const getHydrationObservable$ = (): Observable<T> => {
Expand Down Expand Up @@ -101,15 +107,18 @@ export function createEventStore<T extends object>(

const useStoreValue = <K extends PropertyPath<T>>(
type: K,
options?: { disableCache?: boolean },
options?: { disableCache?: boolean; throtle?: number },
): [GetValueType<T, K>, (payload: GetValueType<T, K>) => void] => {
const disableCache = options?.disableCache ?? false;

const defaultValue: GetValueType<T, K> = get(type, state$.getValue());


const [value, setValue] = useState<GetValueType<T, K>>(defaultValue);


const handleUpdate = useCallback((payload: GetValueType<T, K>) => {
if (!disableCache) setValue(payload);
if (!disableCache) setValue(payload);
publish(type, payload);
}, []);
Expand All @@ -127,7 +136,10 @@ export function createEventStore<T extends object>(
}, []);

useEffect(() => {
const subscription = getPropertyObservable(type).subscribe({
const subscription = getPropertyObservable(
type,
options?.throtle,
).subscribe({
next: (value) => {
setValue(value);
},
Expand All @@ -140,6 +152,7 @@ export function createEventStore<T extends object>(
return [value, handleUpdate];
};


const useHydrateStore = () => {
return useCallback((payload: T) => {
globalEventStore$.next({ type: '@@HYDRATED', payload });
Expand Down

0 comments on commit a769773

Please sign in to comment.