import { is } from '@alloc/is' import { useEffect } from 'react' import { batchedUpdates } from 'react-batched-updates' import { Auto } from '../auto' import { no } from '../no' import { useConstant, useDispose } from './common' import { useDerived } from './useDerived' type Deps = readonly any[] type EffectReturn = void | (() => void | undefined) /** Wrap a `useEffect` call with magic observable tracking */ export function useAuto(effect: () => EffectReturn, deps?: readonly any[]): Auto /** * Combine a `useEffect` call with an `Auto` instance that invokes an * unobserved side `effect` when the `compute` function returns a new value. */ export function useAuto( compute: () => T, effect: (value: T) => EffectReturn, deps?: readonly any[] ): Auto /** @internal */ export function useAuto( computeOrEffect: () => unknown, effectOrDeps?: Function | Deps, deps?: Deps ) { const auto = useConstant(() => new Auto()) useDispose(() => auto.dispose()) let effect: () => EffectReturn if (is.function(effectOrDeps)) { const compute = useDerived(computeOrEffect, deps) effect = () => no(effectOrDeps as any)(compute()) } else { effect = computeOrEffect as any deps = effectOrDeps as any } useEffect( () => batchedUpdates(() => { auto.run(effect) }), deps ) return auto }