I am trying to use lodash's throttle inside a React component to make some other call. This is what I currently have:
const requestDetails = useCallback(
throttle((someId: number) => {
dispatch(...);
}, 30000)
, []);
I am trying to make it so that requestDetails(someId)
only will run dispatch
once every 30 seconds, at most, for each someId
passed.
Therefore, I would need to return a different throttle
function for each someId
. However, the code above doesn't work: I think it is because there is only one throttle
function created behind-the-scenes, and therefore throttle
will only run once every 30 seconds for all calls, not per someId
.
Thank you!
CodePudding user response:
I'd suggest to use useRef
to keep throttled function and call useEffect
to listen to someId
changes
const throttleRef = useRef(throttle((someId: number) => {
dispatch(...);
}, 30000))
useEffect(() => throttleRef.current(someId), [someId])
CodePudding user response:
You'll need to generate a throttled function for each someId
and store them using a ref. Whenever useEffect
is called with a valid someId
(not undefined
), generate and store a function if none exists for this someId
, and then call the function for that someId
.
Define the type of the throttled functions:
import { throttle, DebouncedFunc } from "lodash";
type ThrottledCallId = DebouncedFunc<() => void>;
In you component create a ref with an object that would hold those functions:
const throttlesRef = useRef<Record<number, ThrottledCallId>>({});
In your useEffect
as long as someId
is not undefined
:
- If the
throttlesRef
object doesn't contain a throttled function, create the function for thissomeId
. - Call the throttled function for that
someId
.
Example:
useEffect(() => {
const throttles = throttlesRef.current;
if(someId !== undefined) {
if(!throttles[someId]) {
// create the throttled function for this someId
throttles[someId] = throttle(() => dispatch(someId), 3000);
}
// call the throttled function for this someId
throttles[someId]();
}
}, [dispatch, someId])