1

This problem is hitting on my performance badly. On each state change, my children's are re-rendered. Is there any way to get rid of this? How can I prevent my child components to not get affected from this type of re-renders. Please help.


import React from "react";

const Content = ({children}) => {
  console.log("I am rendering multiple times on each update");

  return children;
};

export default function App() {
  const [open, setOpen] = React.useState(false);

  return (
    <>
      <button onClick={() => setOpen(!open)}>{open ? "Close" : "Open"}</button>

      <Content>
      <p>test-children</p>
      </Content>
    </>
  );
}






  • React.memo for Content – HMR Jun 12 '20 at 12:47
  • @HMR Tried that but it didn't help because sometimes I want to pass children props on Content where memo doesn't support – Anugraha Acharya Jun 12 '20 at 12:58
  • 1
    @AnugrahaAcharya You may find this [detailed answer](https://github.com/facebook/react/issues/15156#issuecomment-474590693) by Dan Abramov helpful. – hangindev.com Jun 12 '20 at 13:13
  • 1
    @AnugrahaAcharya I can't open this question again but you are correct, the component will re render if it has children even if all children themselves are pure components. Maybe you could create a new question specifically asking how to prevent re render when using children. I think that if you're using children then don't have the component do other heavy calculations or rendering, when children are pure then you should not have a performance problem. – HMR Jun 12 '20 at 14:13
  • Thanks @HMR. it helped me. I end up with something like https://codesandbox.io/s/prevent-renders-on-sidebar-toggle-lmo4j?file=/src/App.js:27-68 – Anugraha Acharya Jun 13 '20 at 05:23

2 Answers2

2

Use React.memo which is a higher order component that returns a new memoized component.

The memoized component will not trigger a re-render if it's props haven't changed.

import React from "react";

const Content = () => {
  console.log("I am rendering multiple time on each open sidebar");
  return <div>test-content</div>;
};

const MemoizedContent = React.memo(Content);

export default function App() {
  const [open, setOpen] = React.useState(false);

  return (
    <>
      <button onClick={() => setOpen(!open)}>{open ? "Close" : "Open"}</button>
      <MemoizedContent />
    </>
  );
}

You can learn more about React.memo here

hangindev.com
  • 4,573
  • 12
  • 28
0

To avoid re-rendering you should use React.memo in the component Content component as follows:

const Content = React.memo(() =>  {
...
});

This way the component will shallowly compare the props and only render again when properties changes, which in this case doesn't.

pachonjcl
  • 723
  • 4
  • 11
  • I end up with something like this. By using `react-fast-compare` with `react.memo` https://codesandbox.io/s/prevent-renders-on-sidebar-toggle-lmo4j?file=/src/App.js:27-68 – Anugraha Acharya Jun 13 '20 at 05:25