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