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
throttlesRefobject 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])
