@equinor/fusion-observable
Version:
44 lines • 1.58 kB
JavaScript
import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { useObservableLayoutSubscription } from './useObservableSubscription';
/**
* Hook for extracting state of observable.
* **note** when state changes the consumer of the hook will rerender
*
* @param subject [dep] Observable subject
* @param initial initial value
* @returns current state of observable
*/
export function useObservableState(subject, opt) {
const resolveInitial = useCallback(() =>
/** provided initial value */
opt?.initial ??
/** use subject current value if supported */
subject.value ??
/** nothing to resolve */
undefined, [subject, opt?.initial]);
const initialValue = useRef(resolveInitial());
const [next, setNext] = useState(initialValue.current);
const [error, setError] = useState(null);
const [complete, setComplete] = useState(false);
useLayoutEffect(() => {
initialValue.current = resolveInitial();
}, [resolveInitial]);
/**
* when subject change, reset state
*/
useLayoutEffect(() => {
subject;
setError(null);
setComplete(false);
setNext(initialValue.current);
}, [subject]);
const subscriber = useMemo(() => ({
next: setNext,
error: setError,
complete: () => setComplete(true),
}), []);
useObservableLayoutSubscription(subject, subscriber, opt?.teardown);
return { value: next, error, complete };
}
export default useObservableState;
//# sourceMappingURL=useObservableState.js.map