mirror of
https://github.com/myfatemi04/wheelshare-frontend.git
synced 2025-04-21 19:29:51 -04:00
add store
This commit is contained in:
parent
445a8b7f80
commit
61a526dfeb
|
@ -17,6 +17,8 @@ export default function PoolMap() {
|
||||||
<GoogleMap
|
<GoogleMap
|
||||||
mapContainerStyle={{ width: '400px', height: '400px' }}
|
mapContainerStyle={{ width: '400px', height: '400px' }}
|
||||||
center={center}
|
center={center}
|
||||||
|
onLoad={() => console.log('Loaded Base Map')}
|
||||||
|
onTilesLoaded={() => console.log('Loaded Tile Map')}
|
||||||
>
|
>
|
||||||
<Marker position={position} />
|
<Marker position={position} />
|
||||||
</GoogleMap>
|
</GoogleMap>
|
||||||
|
|
88
src/store.ts
Normal file
88
src/store.ts
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
export type UpdateListener<T> = (newValue: StoreValue<T> | null) => void;
|
||||||
|
|
||||||
|
export type ValueFetcher<T> = (key: string) => Promise<T | null>;
|
||||||
|
|
||||||
|
export type StoreValue<T> = { value: T } | { error: any };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a general-purpose, subscribable key-value store for content like posts, groups, and spaces.
|
||||||
|
*/
|
||||||
|
export class Store<T> {
|
||||||
|
/**
|
||||||
|
* Stores the internal data. If the value is `null`, then we attempted to fetch the data, but it did not exist.
|
||||||
|
*/
|
||||||
|
private data = new Map<string, StoreValue<T> | null>();
|
||||||
|
private listeners = new Map<string, Set<UpdateListener<T>>>();
|
||||||
|
|
||||||
|
constructor(private fetcher: ValueFetcher<T>) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param key The key to get the data for
|
||||||
|
* @param forceRefresh If the data already exists, fetch it again anyway
|
||||||
|
*/
|
||||||
|
get(key: string, forceRefresh = false): StoreValue<T> | null {
|
||||||
|
if (!this.data.has(key) || forceRefresh) {
|
||||||
|
this.fetcher(key)
|
||||||
|
.then((value) => {
|
||||||
|
this.set(key, value ? { value } : null);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.set(key, { error });
|
||||||
|
});
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.data.get(key) ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
set(key: string, value: StoreValue<T> | null) {
|
||||||
|
if (this.listeners.has(key)) {
|
||||||
|
this.listeners.get(key)?.forEach((callback) => {
|
||||||
|
callback(value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.data.set(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribe(key: string, listener: UpdateListener<T>) {
|
||||||
|
if (!this.listeners.has(key)) {
|
||||||
|
this.listeners.set(key, new Set());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.listeners.get(key)?.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsubscribe(key: string, listener: UpdateListener<T>) {
|
||||||
|
if (this.listeners.has(key)) {
|
||||||
|
if (this.listeners.get(key)?.has(listener)) {
|
||||||
|
this.listeners.get(key)?.delete(listener);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn(
|
||||||
|
'Unsubscribed from',
|
||||||
|
key,
|
||||||
|
'but listener does not exist: ',
|
||||||
|
listener
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useStoredValue<T>(store: Store<T>, key: string) {
|
||||||
|
const [value, setValue] = useState<StoreValue<T> | null>(store.get(key));
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const callback = (value: StoreValue<T> | null) => setValue(value);
|
||||||
|
store.subscribe(key, callback);
|
||||||
|
|
||||||
|
return () => store.unsubscribe(key, callback);
|
||||||
|
}, [key, store]);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user