React - how to replace useCallback hook with useMemo?

1.6k Views Asked by At

I am reading this article about memoization in React, and I wonder how can I translate and use useMemo instead of useCallback hook. In particular for this example:

<Child name={ useCallback(() => {console.log('Really Skinny Jack')}, [])  } />

Where Child component looks like this:

export default React.memo(function Child({ name }) {
  console.log("Child component");
  return (
    <>
      {name()}
      <div>Child component</div>
    </>
  );
});

If I try to replace this with useMemo:

  <Child
    name={useMemo(() => {
      console.log("useMemo");
    }, [])}
  />

I get an error:

TypeError name is not a function

I also tried like this:

  {useMemo(
    <Child
      name={() => {
        console.log("useMemo");
      }}
    />,
    []
  )}

But, then I get:

TypeError nextCreate is not a function

So, I how am I suppose to replace useCallback with useMemo in this example?

3

There are 3 best solutions below

0
On BEST ANSWER

With useMemo, you can do it like this

<Child
  name={useMemo(() => {
    // return the function or anything you want react to memoize
    return () => {
      console.log('useMemo');
    };
  }, [])}
/>

With useMemo, whatever you return from the useMemo's callback will be memoized. On the other hand, useCallback is used to memoize functions only.

Some key differences to note

useMemo

Used to memoize functions, arrays, objects, etc.

const memoizedList = useMemo(() => {
  return [1, 2, 3];
}, []);

const memoizedFunction = useMemo(() => {
  return () => {
    console.log('I am meoized');
  };
}, []);

useCallback

Used to memoize functions

const memoizedFunction = useCallback(() => {
  console.log('I am meoized');
}, []);

React.memo

A Higher-Order Component to memoize React components

const MyComponent = (props) => {
  return "I am a memoized component";
}
export default React.memo(MyComponent);
0
On

Try to replace it like this

<Child name={React.useMemo(() => () => alert(55), [])} />
0
On

So, I how am I suppose to replace useCallback with useMemo in this example?

The useCallback hook returns a memoized callback function that is passed to it whereas the useMemo hook takes a function callback and returns a memoized value.

From the useCallback docs:

useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).

The following are equivalent implementations:

  1. useCallback

    const nameHandler = useCallback(() => {
      console.log('Really Skinny Jack');
    }, []);
    ...
    <Child name={nameHandler} />
    
  2. useMemo

    const nameHandler = useMemo(() => () => {
      console.log('Really Skinny Jack');
    }, []);
    ...
    <Child name={nameHandler} />
    

The useMemo hook is taking a callback that returns a function that is being used and passed as a callback to a child component.

It isn't really clear at all why you would want to do this though. The useCallback hook is the intended hook to be used when you want to memoize a callback that is passed to children components. It's also a lot clearer and easier to read than the "double" function that is used in the useMemo version. I suggest sticking to the useCallback version of your code.