Home > other >  react: memoize a function based on a parameter passed to said function
react: memoize a function based on a parameter passed to said function

Time:11-12

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:

  1. If the throttlesRef object doesn't contain a throttled function, create the function for this someId.
  2. 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])
  • Related