Last active
November 5, 2020 22:14
-
-
Save rpggio/aa4b0615e2f83df11767141f2cfb6009 to your computer and use it in GitHub Desktop.
Basic reactive store
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { Reactive, Subscriber, Store } from './types' | |
export function Store<S>(initial: S): Store<S> { | |
let current = initial | |
const subscribers = new Set<Subscriber<S>>() | |
function subscribe(subscriber: Subscriber<S>) { | |
subscribers.add(subscriber) | |
return () => unsubscribe(subscriber as VoidFunction) | |
} | |
function unsubscribe(subscriber: VoidFunction) { | |
subscribers.delete(subscriber) | |
} | |
function writeState(newState: S) { | |
current = newState | |
for (const subscriber of subscribers) { | |
subscriber(newState) | |
} | |
} | |
return { | |
subscribe, | |
unsubscribe, | |
getState() { | |
return current | |
}, | |
setState(setter: S | ((s: S) => S)) { | |
if (typeof setter === 'function') { | |
writeState((setter as ((s: S) => S))(current)) | |
} else { | |
writeState(setter as S) | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export type Reactive<T> = { | |
subscribe(subscriber: Subscriber<T>): VoidFunction | |
unsubscribe(subscriber: VoidFunction): void | |
} | |
export type Subscriber<S> = (s: S) => void | |
export type Store<S> = Reactive<S> & { | |
getState(): S | |
setState(setter: S | ((s: S) => S)): void | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useState } from 'react' | |
import type { Reactive, Store } from './types' | |
export function useStore<S>(store: Store<S>) { | |
const { getState, setState, subscribe } = store | |
const initial = getState() | |
const [state, setLocalState] = useState<S>(initial) | |
useEffect(() => subscribe(setLocalState), [subscribe]) | |
return tuple( | |
state, | |
setState, | |
store | |
) | |
} | |
function tuple<T extends any[]>(...elements: T) { | |
return elements | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment