Mobx: Reaction delay throttling instead of debouncing

Created on 29 Apr 2019  ·  11Comments  ·  Source: mobxjs/mobx

Hi,

As stated in the documentation for reaction

Options
delay: Number in milliseconds that can be used to debounce the effect function. If zero (the default), no debouncing will happen.

The delay option should debounce the reaction, but in fact it throttles it.
Is the documentation incorrect or is it a bug?

🍗 enhancement 📖 documentation

Most helpful comment

That's what I ended up doing yes.
I think it'd be great to have a debounceDelay option that provides this out of the box :)

All 11 comments

Feel free to update the docs. Note that a custom scheduler can be set to customize the behavior

I'm failing to use scheduler to achieve debouncing

let id;
...
delay: 0,
scheduler: f => {
    clearTimeout(id);
    id = setTimeout(f, 1000);
}

It's still throttling and not clearing the timeout if a reaction has been done in those 1000ms timeout

well, you would have to wrap the reaction function itself as well, and
introduce some state in the closure to take care of the throttling process.

On Tue, Apr 30, 2019 at 2:41 PM Bap ☺ notifications@github.com wrote:

I'm failing to use scheduler to achieve debouncing

let id;...
delay: 0,scheduler: f => {
clearTimeout(id);
id = setTimeout(f, 1000);
}

It's still throttling and not clearing the timeout if a reaction has been
done in those 1000ms timeout


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/mobxjs/mobx/issues/1956#issuecomment-487935787, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAN4NBGG5KYX4PP2EETUVMLPTA47BANCNFSM4HI7RD3Q
.

That's what I ended up doing yes.
I think it'd be great to have a debounceDelay option that provides this out of the box :)

Agree that there is some confusion between throttling/debouncing. This is my take on achieving true debouncing.

function debounceEffect<T>(effect: (arg: T, r: IReactionPublic) => void, debounceMs: number) {
    let timer: NodeJS.Timeout
    return (arg: T, r: IReactionPublic) => {
        clearTimeout(timer)
        timer = setTimeout(() => effect(arg, r), debounceMs)
    }
}

// Use it like so:
reaction(
    () => this.searchTextField,
    debounceEffect(s => this.searchString = s, 1000)
)

Docs fixed in #2337

function debounceEffect<T>(effect: (arg: T, r: IReactionPublic) => void, debounceMs: number) {
    let timer: NodeJS.Timeout
    return (arg: T, r: IReactionPublic) => {
        clearTimeout(timer)
        timer = setTimeout(() => effect(arg, r), debounceMs)
    }
}

@koffmoff I tried to use this utility func to run a function which returns a Promise<void> instead of an assignment inside my reaction, but couldn't make it work, what am I missing?

@pkhodaveissi should work. Msg your code + error to me if you want.

@pkhodaveissi should work. Msg your code + error to me if you want.

@koffmoff
There it is:

const disposePaginationReaction = reaction(
        () => ({
          pageSize: self.pagination.pageSize,
          pageIndex: self.pagination.pageIndex,
        }),
        () => {
          getItems(true, false);
        }
      );


//and the getItems:
const getItems = flow(function* getQueuesFLow(
      shouldShowLoading: boolean = true,
      shouldResetPagination: boolean = true
    ) {
// some work to yield an API call
});

Typescript complains about passing Promise<void> instead of (arg: T, r: IReactionPublic) => void when I tried to replace debounceEffect(s => this.searchString = s, 1000) with something like debounceEffect(self.getItems(), 1000).

Thanks for your time man.

p.s.: I'm using mobx along MST

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs or questions.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs or questions.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mdebbar picture mdebbar  ·  3Comments

geohuz picture geohuz  ·  3Comments

hellectronic picture hellectronic  ·  3Comments

rodryquintero picture rodryquintero  ·  3Comments

ansarizafar picture ansarizafar  ·  4Comments