wana
Version:
Easy observable state for React
36 lines (31 loc) • 909 B
text/typescript
import { useLayoutEffect } from 'react-layout-effect'
import { useMemoOne as useMemo } from 'use-memo-one'
import { emptyArray } from '../common'
import { no } from '../no'
import { Change, ChangeObserver, ObserverTarget } from '../observable'
import { $O } from '../symbols'
/** Listen for shallow changes to an observable object. */
export function useChanges(
target: ObserverTarget,
onChange: (change: Change) => void,
deps?: readonly any[]
) {
const observable = target[$O]
if (!observable) {
throw Error('Expected an observable object')
}
const observer = useMemo<ChangeObserver>(
() => ({ onChange } as any),
emptyArray
)
useLayoutEffect(() => {
observer.onChange = no(onChange)
}, deps)
useLayoutEffect(() => {
const observers = observable.get($O)
observers.add(observer)
return () => {
observers.delete(observer)
}
}, [observable])
}