import { useEffect, useState } from "react"; export class Sub { _listeners: ((obj: T) => void)[] = []; _current: T | null = null; subscribe(listener: any) { if (this._listeners.indexOf(listener) < 0) { this._listeners.push(listener); } } unsubscribe(listener: any) { const index = this._listeners.indexOf(listener); if (index >= 0) { this._listeners.splice(index, 1); } } get(): T | null { return this._current; } set(obj: T) { this._current = obj; this._listeners.forEach((cb) => cb(obj)); } } export function useSub( sub: Sub, effectChanges: ((v: T | null) => any[]) | null = null ): T | null { const [currentState, stateSetter] = useState(sub.get()); useEffect( () => { const listener = (obj: T) => stateSetter(obj); sub.subscribe(listener); return () => sub.unsubscribe(listener); // This effect uses "sub" from outside of its scope, should it be a dependency? // Ignore the lint warning for now. // eslint-disable-next-line }, effectChanges ? effectChanges(currentState) : [] ); return currentState; }