Search code examples
javascriptreactjsreact-functional-componentreact-memo

Why is the (memoized) child component re-rendering?


I have two React functional components: C1 and C2. C2 is nested inside C1:

const C2 = () => {
  console.log("C2 Render");
  return (
    <div>I am Component 2</div>
  );
};

const C1 = () => {
  const [text, setText] = useState("Hello");
  const MC2 = React.memo(C2, () => true);
  
  return (
    <div className="box">
      <h1>The Button</h1>  
      <button
        onClick={() => {
          setText(`${text} b`);
        }}
        className="button">
          Click me
       </button>
      <div>
        {text}
      </div>
      <MC2 />
    </div>
  );
}

CodePen here.

The problem

I know that a component gets re-rendered under different situations. Among those is the one when the parent re-renders.

That is why I am using a memoized component around C2. But still I can see the console displaying "C2 Render" every time I click the button.

Why?


Solution

  • C1 rerender because of state chnage, so your memoized component is redeclared every time. just wrap C2 in a React.memo() & you would not see the rerenders

    const MC2 = React.memo(() => {
      console.log("C2 Render");
      return (
        <div>I am Component 2</div>
      );
    }, () => true);
    

    or if you want to memoize only one useCase put it outside the C1 component and have that component memoized:

    const C2 = () => {
      console.log("C2 Render");
      return (
        <div>I am Component 2</div>
      );
    };
    
    const MC2 = React.memo(C2, () => true);
    

    & used it like this:

    const C1 = () => {
      const [text, setText] = useState("Hello");
      
      return (
        <div className="box">
          <h1>The Button</h1>  
          <button
            onClick={() => {
              setText(`${text} b`);
            }}
            className="button">
              Click me
           </button>
          <div>
            {text}
          </div>
          <MC2 />
        </div>
      );
    }