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?
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.
Most helpful comment
That's what I ended up doing yes.
I think it'd be great to have a
debounceDelayoption that provides this out of the box :)