4

I really like the API of React's useMemo hook, where you write a function and list its dependencies in an array:

const memoizedValue = useMemo(
  () => computeExpensiveValue(a, b),
  [a, b]
);

It has the downside, however, that it can only be used inside a React function component. How can I implement something with the same API that can be used anywhere?

(Clarification)

I understand what memoization is. I'm talking specifically about the useMemo hook's API. Whereas most memoization libraries take a function and return a memoized version of that function, useMemo takes a function and an arguments list and returns a value. There are no wrapped functions exposed to the user.

The other interesting part of this API is that repeated calls to useMemo will use the same cache, even though a new anonymous function is being created on every call (full example on codepen):

import {useMemo} from 'react';
import ReactDOM from 'react-dom';

function computeExpensiveValue(a, b) {
  console.log('computing expensive value');
  return a + b;
}
function MyComponent(props) {
  const {a, b} = props;
  const memoizedValue = useMemo(
    () => computeExpensiveValue(a, b),
    [a, b]
  );
  return <div>{memoizedValue}</div>
}
for (const i of [1, 2, 3]) {
  ReactDOM.render(<MyComponent a={1} b={2} />, el);
}

This only logs "computing expensive value" once, even though three different functions are passed to useMemo. Clearly useMemo is using something other than the function object as its cache key, and that's the truly interesting part of its API.

danvk
  • 15,863
  • 5
  • 72
  • 116
  • Do you just mean how to implementation memoization generally? See e.g. https://stackoverflow.com/questions/30386943/how-to-create-a-memoize-function. – jonrsharpe Sep 11 '19 at 20:06
  • It isn't clear what you're asking. A react functional component is stateless so it can't save a value in a way that lets you read it every time you call the function. Outside of a functional component, you can just assign the computed value to a variable or a data structure, like a dictionary, and read the value as usual – Christopher Francisco Sep 11 '19 at 20:06
  • Yes, I'm asking about memoization generally. Most memoization libraries have an API that takes a function and returns a new, wrapped function. I like the React `useMemo` API, which returns a value, not a wrapped function. I'm asking how I'd implement something like it myself. – danvk Sep 11 '19 at 20:14
  • I have been using memoizeone and re-select libraries for acheiving memoization outside react component. memoizeone: https://www.npmjs.com/package/memoize-one works in a similar way. the new value is computed only when the arguments change. If you are using reselect library in your project then defining selectors for the computations done on store variables might be an even better solution. That follows a similar computation logic as useMemo. – ggsrivas May 11 '21 at 18:24

0 Answers0