Skip to content

Instantly share code, notes, and snippets.

@oWeRQ
Last active June 14, 2023 10:19
Show Gist options
  • Save oWeRQ/5eca724cb3a16531313cf5ad3b0907d4 to your computer and use it in GitHub Desktop.
Save oWeRQ/5eca724cb3a16531313cf5ad3b0907d4 to your computer and use it in GitHub Desktop.
import { useEffect, useMemo, useRef } from 'react';
export interface Listener<T> {
(value: T): void;
}
export interface ObservableRef<T> {
(value: T): void;
current: T;
subscribe(listener: Listener<T>): () => void;
unsubscribeAll(): void;
}
export function createObservableRef<T>(initialValue: T): ObservableRef<T> {
const listeners = new Set<Listener<T>>();
let currentValue = initialValue;
function observableRef(value: T) {
currentValue = value;
listeners.forEach(listener => listener(value));
}
observableRef.subscribe = (listener: Listener<T>) => {
listeners.add(listener);
return () => {
listeners.delete(listener);
};
};
observableRef.unsubscribeAll = () => {
listeners.clear();
};
observableRef.current = currentValue;
Object.defineProperty(observableRef, 'current', {
get(): T {
return currentValue;
},
set(value: T) {
observableRef(value);
},
});
return observableRef;
}
export function useObservableRef<T>(initialValue: T) {
const valueRef = useRef<T>(initialValue);
const observableRef = useMemo(() => createObservableRef(valueRef.current), []);
useEffect(() => {
return observableRef.unsubscribeAll;
}, [observableRef]);
return observableRef;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment