11

This is common explaination about useMemo hook in React.js

useMemo(compute, dependencies) invokes compute, memoizes the calculation result, and returns it to the component.

If during next renderings the dependencies don’t change, then useMemo() doesn’t invoke compute but returns the memoized value.

- Dmitri Pavlutin

However, I saw the example of useMemo hooks that returns an array like this below.

React.useMemo(() => [1, 2, 3], []);

As you can see, useMemo returns an array which is considered as an object in Javascript.

This is confusing. I thought usage of useMemo hook is for memoizing calculated value.

So I did a little test to figure out how useMemo with object works

const Child = React.memo(({ obj }) => {

  console.log('this is child component')

  return <div>Child Component</div>
})

const App = () => {
  const [toggle, setToggle] = React.useState(false)

  const memoObj = React.useMemo(() => { return { bar: 'foo' } }, [])

  return (
    <div>
      <button onClick={() => setToggle(!toggle)}>test</button>
      <Child obj={memoObj} />
    </div>
  );
}

When memoObj is not wrapped by useMemo, whenever I click test button, I can see the message from Child component in console.

On the other hand, when memoObj is wrapped by the hook, the message shows up only when Child component rendered first time.

Does it mean that useMemo not only memoize calculated value but also reference of an object as well?

2 Answers 2

9

Does it mean that useMemo not only memoize calculated value but also reference of an object as well?

Yes of course and does not re-render the memoized component until is necessary to re-render it (like something has changed).

BUT you have to keep in mind that:

By default it will only shallowly compare complex objects in the props object.

So

If you want control over the comparison, you can also provide a custom comparison function as the second argument.

function MyComponent(props) {
  /* render using props */
}
function areEqual(prevProps, nextProps) {
  /*
  return true if passing nextProps to render would return
  the same result as passing prevProps to render,
  otherwise return false
  */
}
export default React.memo(MyComponent, areEqual);

This is what React says.

Sign up to request clarification or add additional context in comments.

1 Comment

Wrong answer. He asks useMemo hook. useMemo doesn't make shallow compare, if ref object mutates, it will run again. If you want to optimize useMemo you can use object properties in the useMemo dependency array.
4

That is true, useMemo will always keep the reference to the object from the last renders while useCallback keep the reference of function (also an object) from the last renders

Your example is also a great way to see how useMemo works!

You could also create the same example for useCallback, this will give the same behaviour

const Child = React.memo(({ obj }) => {
   console.log('this is child component');

   return <div>Child Component</div>;
});

const App = () => {
   const [toggle, setToggle] = React.useState(false);

   const useCallbackObj = React.useCallback(() => {
      console.log('callback is called!');
   }, []);

   return (
      <div>
         <button onClick={() => setToggle(!toggle)}>test</button>
         <Child obj={useCallbackObj} />
      </div>
   );
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.