import { useSyncExternalStore } from 'react' type Subscriber = (value: T) => void type Fulfilled = { status: 'fulfilled' payload: T } type Rejected = { status: 'rejected' payload: unknown } type Pending = { status: 'pending' payload: Promise } type Value = Fulfilled | Rejected | Pending export type Store = ReturnType> export const createStore = () => { const subscribers: Array> = [] let resolve: undefined | (() => void) let value: Value = { status: 'pending', payload: new Promise((res) => (resolve = res)), } const set = (val: T) => { if (value.status === 'pending') { resolve?.() } value = { status: 'fulfilled', payload: val, } for (const sub of subscribers) { sub(val) } } const reject = (val: unknown) => { if (value.status === 'pending') { resolve?.() } value = { status: 'rejected', payload: val, } } const read = (): T => { if (value.status === 'fulfilled') { return value.payload } if (value.status === 'pending') { // eslint-disable-next-line @typescript-eslint/no-throw-literal throw value.payload } throw value.payload } const subscribe = (sub: Subscriber) => { const index = subscribers.length subscribers.push(sub) return () => { subscribers.splice(index, 1) } } return { set, read, reject, subscribe, } } export function useStore(store: Store) { return useSyncExternalStore(store.subscribe, store.read, store.read) }