Skip to content

Instantly share code, notes, and snippets.

@krstffr
Created December 16, 2016 12:04
Show Gist options
  • Star 51 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save krstffr/245fe83885b597aabaf06348220c2fe9 to your computer and use it in GitHub Desktop.
Save krstffr/245fe83885b597aabaf06348220c2fe9 to your computer and use it in GitHub Desktop.
Debouncing redux thunk actions.
// A common redux pattern when dealing with async functions is to use thunk.
// This usually means your action returns a new function instead of an action object,
// and the thunk middleware will make it all work. Example:
const asyncAction = () => dispatch => setTimeout(() => dispatch(someOtherAction()), 10000);
// Now: maybe that async stuff going on is calling some API which you don't want to overload
// with request, and that's what debounce is for.
// This is an example of a debounced function which will only be calleable once every second.
import { debounce } from 'lodash';
const debouncedFn = debounce(() => callApi(), 1000, { leading: true, trailing: false });
// This will only call the function once since its debounced:
debouncedFn();
debouncedFn();
debouncedFn();
// If you want to do this in your redux thunk actions, you need to think about a few things.
// 1. In our example thunk action above the returned function is defined every time the outer
// function is called, meaning that if we were to wrap it in debounce() it would just call a
// new version of that function every time, which would of course call it every time.
// 2. Ehm, that's really the only thing you need to think about!
// How do we solve this? Define the inner function outside of the wrapping function of course.
// So: this will NOT work:
const asyncActionNOTDebounced = () => debounce(dispatch => setTimeout(() => dispatch(someOtherAction()), 10000), 1000);
// But this will work since the inner function is only "created" once:
const innerFunction = debounce(dispatch => setTimeout(() => dispatch(someOtherAction()), 10000), 1000);
const asyncActionDebounced = () => innerFunction;
@abustamam
Copy link

Excellent! Very helpful. What if you want to pass in arguments to innerFunction though? If you have a payload or something?

@panayi
Copy link

panayi commented Dec 22, 2017

@abustamam

const innerFunction = debounce((dispatch, ...args) => setTimeout(() => dispatch(someOtherAction(...args)), 10000), 1000);
const asyncActionDebounced = (...args) => dispatch => innerFunction(dispatch, ...args);

@gautammadaan
Copy link

Thank you @panayi. The solution worked for my case as well. I had to pull the debounce out of the mapDispatchToProps to prevent it from re-initializing again and again. I did not use setTimeout though, called the API method directly.

@CodHeK
Copy link

CodHeK commented Mar 12, 2021

Thank you so much! :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment