Why the useMemo is not working? Am I using it wrong?

Viewed 12525

So I am just getting the hang of useMemo and useCallback and playing around to see how things are working. What I want to do in this scenario is not to render the Child whenever the parent is sending the same object.

Here is my Parent component:


const Parent = () => {
  const [value, setValue] = useState(0);
  const handleOnClick = e => {
    setValue(value + 1);
  };

  const myObject = useMemo(() => {
    return { value: value - value };
  }, [value]);

  return (
    <div>
      <h1>I am a parent</h1>
      <button onClick={handleOnClick}>
        Click on Me
      </button>
      <Child object={myObject} />
    </div>
  );
};

export default Parent;

And here is my Child which is re-rendering on each click although the content of "myObject" is the same. (I know the reference changes each time but my understanding is that's what useMemo does)

const Child = ({ object }) => {
  return (
    <div>
      <h1>I am child</h1>
      <p>Object is {JSON.stringify(object)}</p>
    </div>
  );
};

export default React.memo(Child);

Here is the Sandbox.

Please let me know what am I doing wrong and what's the solution for this case?

1 Answers

The dependency array is what controls when the memoization breaks. If anything in that array has changed, then the memoization runs again. React only checks that array though, not the finished product.

Right now you're telling it to recompute any time value changes. You can provide something else to the array if value is not what you want. Your example of value - value doesn't make much sense since it will never change, so let me replace it which will change half of the time:

const Parent = () => {
  const [value, setValue] = useState(0);
  const handleOnClick = e => {
    setValue(value + 1);
  };

  const halfValue = Math.round(value / 2);
  const myObject = useMemo(() => {
    return { halfValue: halfValue };
  }, [halfValue]);

  return (
    <div>
      <h1>I am a parent</h1>
      <button onClick={handleOnClick}>
        Click on Me
      </button>
      <Child object={myObject} />
    </div>
  );
};

Now the memoization will be recomputed on every other click.

Related