3

I have a component that I reuse most of its logic. I'm looking to avoid re-renders on its children components which happen every time I hover over the parent:

const ReusableComponent = ({ conditional }) => {
  const [isHovered, setIsHovered] = useState(false);

  const AnotherReusableComponent = ({ children }) => (
    <div>{children}</div>
  );

  const renderComponent = () => {
    if (conditional) {
      return <ComponentA />;
    };

    return <ComponentB />;
  };

  return (
    <div>
      <title 
        onMouseEnter={() => setIsHovered(true)}
        onMouseLeave={() => setIsHovered(false)}
      >
        Menu
      </title>
      <div className={isHovered ? 'oneClass' : 'otherClass'}>
        <AnotherReusableComponent>
          {renderComponent()}
        </AnotherReusableComponent>
      </div>
    </div>
  );
}

Notes:

  • ComponentA and ComponentB are shown/hidden depending on className
  • onHover event toggles className
  • Tried memo, didn't work.
  • The re-render happens onHover
phuzi
  • 12,078
  • 3
  • 26
  • 50

1 Answers1

0
  1. First, Components should never be declared inside other components, since they will be recreated at each render unless you memoize them with useMemo.
  2. Even if you declare it outside you will experience a re-render of <AnotherReusableComponent> and its children when isHovered changes, hence you need to wrap it into React.memo() to ensure it won't re-render unless its props change:
 const AnotherReusableComponent = React.memo(({ children }) => (
    <div>{children}</div>
  ));

const ComponentA = React.memo(() => (
    <div>A</div>
  ));

const ComponentB = React.memo(() => (
    <div>B</div>
  ));

const ReusableComponent = ({ condition }) => {
  const [isHovered, setIsHovered] = useState(false);

  return (
    <div>
      <title 
        onMouseEnter={() => setIsHovered(true)}
        onMouseLeave={() => setIsHovered(false)}
      >
        Menu
      </title>
      <div className={isHovered ? 'oneClass' : 'otherClass'}>
        <AnotherReusableComponent>
          {condition ? <ComponentA/> : <ComponentB/>}
        </AnotherReusableComponent>
      </div>
    </div>
  );
}


This should avoid the re-render of AnotherReusableComponent and its children unless condition changes.

Cesare Polonara
  • 3,473
  • 1
  • 9
  • 19