Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does useMemo hooks in React.js also memoizes object reference as well?

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?

like image 585
GoonGamja Avatar asked Mar 31 '26 18:03

GoonGamja


2 Answers

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.

like image 120
Giovanni Esposito Avatar answered Apr 03 '26 09:04

Giovanni Esposito


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>
   );
};
like image 35
Ryan Le Avatar answered Apr 03 '26 09:04

Ryan Le



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!