Hafiz Temuri
Hafiz Temuri

Reputation: 4142

How to make JavaScript function runs only when parameter changes

I am using React and every time something changes it renders the whole component. Although I have a smallest possible component, but it runs a heavy function. I don't want this function to run on every render if its parameters has not changed. Something like React.memo (basically don't re-render a component if its props have not changed). Is there an equivalent of React.memo for static JavaScript functions?

NOTE: I don't want to pull in a library such as reselect. There has to be a better way!


Edit: I feel like I was not very clear about what I was looking for. Let me ask this with an example,

https://codesandbox.io/s/react-typescript-2xe2m?expanddevtools=1&fontsize=14&hidenavigation=1&theme=dark

Every time I click on + or -, it runs the pleaseMemoizeThisFunction function, even though its parameter has not changed. How can I have this function only runs when any of its parameters change.

Upvotes: 1

Views: 2147

Answers (2)

Thomas
Thomas

Reputation: 12677

This is a simple memoization implementation that checks wether the function is called with the same arguments as the last time, and only recalculates the result if they differ.

Seing in your sandbox that you use Typescript, I've added the Types to this function.


function memo<A extends any[], R>(fn:(...args:A) => R) {
  let value:R, 
    before: A = {length:NaN} as any;

  const sameAsBefore = (v:A[number], i:number) => v === before[i];
  function memoized (...args:A):R {
    if (args.length !== before.length || !args.every(sameAsBefore)) {
        before = args;
        value = fn.apply(this, args);
    }
    return value;
  }


}

usage:

const pleaseMemoizeThisFunction = memo((a: string, b: string): string => {
  console.count("function run: ");
  // it will do some heavy stuff here
  return `I am done with ${a} and ${b}`;
});

or like this.someMethod = memo(this.someMethod);

Upvotes: 0

Daniel Duong
Daniel Duong

Reputation: 1104

Use the useMemo hook around your functions and it will not run unless the params have changed. https://reactjs.org/docs/hooks-reference.html#usememo

const computed = useMemo(() => calculateExpensive(param1, param2), [param1, param2]);

Upvotes: 1

Related Questions