import { useSignal } from '../lib/teact/teact'; import type { Signal } from '../util/signals'; import { useSignalEffect } from './useSignalEffect'; import { useStateRef } from './useStateRef'; import useSyncEffect from './useSyncEffect'; type SyncResolver = () => T; type AsyncResolver = (setter: (newValue: T) => void) => void; type Resolver = SyncResolver | AsyncResolver; function useDerivedSignal(resolver: SyncResolver, dependencies: readonly any[]): Signal; function useDerivedSignal(resolver: AsyncResolver, dependencies: readonly any[], isAsync: true): Signal; function useDerivedSignal(dependency: T): Signal; function useDerivedSignal(resolverOrDependency: Resolver | T, dependencies?: readonly any[], isAsync = false) { const resolver = dependencies ? resolverOrDependency as Resolver : () => (resolverOrDependency as T); dependencies ??= [resolverOrDependency]; const [getValue, setValue] = useSignal(); const resolverRef = useStateRef(resolver); function runCurrentResolver() { const currentResolver = resolverRef.current; if (isAsync) { (currentResolver as AsyncResolver)(setValue); } else { setValue((currentResolver as SyncResolver)()); } } // eslint-disable-next-line react-hooks-static-deps/exhaustive-deps useSyncEffect(runCurrentResolver, dependencies); // eslint-disable-next-line react-hooks-static-deps/exhaustive-deps useSignalEffect(runCurrentResolver, dependencies); return getValue as Signal; } export default useDerivedSignal;