import {useEffect, useState} from 'react'; export default class StateMapper { private getFun: () => T; private cbs: Set = new Set([]); constructor(getFun: () => T) { this.getFun = getFun; } notify = () => { this.cbs.forEach(_ => _?.()); }; useMappedState = () => { const [_state, _setState] = useState(this.getFun); const updateState = () => { _setState(this.getFun()); }; useEffect(() => { this.cbs.add(updateState); return () => { this.cbs.delete(updateState); }; }, []); return _state; }; } type UpdateFunc = (prev: T) => T; export class GlobalState { private value: T; private stateMapper: StateMapper; constructor(initValue: T) { this.value = initValue; this.stateMapper = new StateMapper(this.getValue); } public getValue = () => { return this.value; }; public useValue = () => { return this.stateMapper.useMappedState(); }; public setValue = (value: T | UpdateFunc) => { let newValue: T; if (typeof value === 'function') { newValue = (value as UpdateFunc)(this.value); } else { newValue = value; } this.value = newValue; this.stateMapper.notify(); }; }