TL;DR I am running into strangeness with creating a throttled function where I need to pass parameters to this method manually while creating the throttled function. I can do this by changing my original function, but I don't want to do this for all my old legacy functions/action creators.
The function passed to throttle:
Note: these are redux action creators.
const changeValue = (value: string, otherValue?: boolean) => {
return {
type: "SOME_TYPE",
payload: {
value: value,
otherValue: otherValue || false
}
};
};
The creation of the throttled function:
const throttledMethod = (value: number, otherValue:boolean ) => {
throttle(changeValue(Number(value),otherValue), 175, { "trailing": false });
};
This normally expects a function to be passed and not the invocation, but then how can I pass parameters unless I am invoking? I don't want to curry in this situation.
The error produced:
node_modules\lodash\throttle.js:56 Uncaught TypeError: Expected a function
at throttle (node_modules\lodash\throttle.js:56)
When break pointed at line 56 in lodash and inspected we see that the value of the object returned from valueChanged:
{
type: "SOME_TYPE",
payload: {
value: value,
otherValue: otherValue || false
}
That is all fair enough.
The strangeness is that we get this to work by doing some relatively dirty manual work in the Redux action creator. I call this dirty because I don't want to change all of my old legacy action creators for this new thing I am doing.
When I manually wrap my action creator like so with the Redux.js dispatch method everything starts working as expected.:
const changeValue = (value: string, otherValue?: boolean) => {
return function (dispatch) {
dispatch({
type: "SOME_TYPE",
payload: {
value: value,
otherValue: otherValue || false
}
});
};
};
So in the end this isn't really so much of an issue with Lodash, but still maybe we could address how to properly pass parameters to a method that needs to be passed to throttled without changing my all of my original methods or currying. Currying confuses a lot of people and in some situations I do somewhat want to pander to the less literate.
Perhaps we can create a wrapper that handles manually wrapping dispatch when passing to lodash throttle or other methods. I think something like that would be ideal, but can't imagine what this wrapper would look like.
Perhaps this is something I might ask the authors about, but first I wanted to attempt "userland".
First, you can get throttle to work by wrapping the invocation in an anonymous function:
const throttledMethod = (value: number, otherValue: boolean) => {
throttle(
() => changeValue(Number(value), otherValue),
175,
{ "trailing": false }
);
};
However, calling throttledMethod()
will just invoke throttle
which returns a throttled version of changeValue
. It doesn't invoke the resulting throttled function. Additionally, changeValue
is just an action creator--it doesn't actually do anything.
Your second action creator that returns (dispatch) => {}
is using redux-thunk. That's good because we're going to need it.
You can get the functionality you're looking for with this:
// we only want to set up the throttling once
const throttledChangeValue = throttle(
(dispatch, value, otherValue) => dispatch(changeValue(Number(value), otherValue)),
175,
{ "trailing": false }
);
// this is using thunk to dispatch the throttled action
const throttledPayOff = (value, otherValue) => dispatch => throttledChangeValue(dispatch, value, otherValue);