import type { IReactionDisposer, IReactionOptions, IReactionPublic } from 'mobx'; import { reaction } from 'mobx'; import { debounce, omit } from 'radash'; export function disposableReaction( disposeExpression: () => boolean, expression: (r: IReactionPublic) => T, effect: ( arg: T, prev: FireImmediately extends true ? T | undefined : T, r: IReactionPublic ) => void, reactionOpts?: IReactionOptions ) { let disposer: IReactionDisposer | undefined; if (!disposeExpression()) { disposer = reaction(expression, effect, reactionOpts); } function cleanDisposer() { disposer = undefined; } reaction(disposeExpression, (mustBeDisposed) => { if (mustBeDisposed) { if (disposer !== undefined) disposer(); cleanDisposer(); } else { setTimeout(() => { disposer = reaction( expression, effect, reactionOpts ? omit(reactionOpts, ['fireImmediately']) : undefined ); }, 100); } }); } export function debouncedReaction( expression: (r: IReactionPublic) => T, effect: ( arg: T, prev: FireImmediately extends true ? T | undefined : T, r: IReactionPublic ) => void, { wait, ...reactionOpts }: IReactionOptions & { wait: number } ): IReactionDisposer { const debouncedEffect = debounce({ delay: wait }, effect); return reaction(expression, debouncedEffect, reactionOpts); } export function disposableDebouncedReaction( disposeExpression: () => boolean, expression: (r: IReactionPublic) => T, effect: ( arg: T, prev: FireImmediately extends true ? T | undefined : T, r: IReactionPublic ) => void, { wait, ...reactionOpts }: IReactionOptions & { wait: number } ) { const debouncedEffect = debounce({ delay: wait }, effect); let disposer: IReactionDisposer | undefined; if (!disposeExpression()) { disposer = reaction(expression, debouncedEffect, reactionOpts); } function cleanDisposer() { disposer = undefined; } reaction(disposeExpression, (mustBeDisposed) => { if (mustBeDisposed) { if (disposer !== undefined) disposer(); cleanDisposer(); } else { setTimeout(() => { disposer = reaction( expression, debouncedEffect, reactionOpts ? omit(reactionOpts, ['fireImmediately']) : undefined ); }, 100); } }); }