<
<

re-renders

<
Hey there! 👋
I need some help!
I'm adding a small feature to our React social app, a floating action button (FAB) to create new posts
Here's the original code:
const App = () => {
  console.log('other code here')
  return (
    <div className="main">
      <Posts config={configs}/>
      <Settings />
      <AdServe id={adId}/>
    </div>
  );
};
And this is my approach:
const App = () => {
  const [isModalOpen, setModalOpen] = useState(false);

  console.log('other code here')
  return (
    <div className="main">
      <Posts
        config={configs}
        data={posts}
      />
      <Settings />
      <AdServe id={adId}/>
      <FAB
        onClick={() => setModalOpen(true)}
        icon={"lg_plus"}
      />
      { isModalOpen &&
        <CreatePostModal onCreated={handleCreatePost}/> }
    </div>
  );
};
The dialog opens fine, but the performance isn't great, the dialog the dialog takes a few seconds to open. Can we figure out why?
<
Hey! Absolutely, let's dive in.
Have you noticed that the App component rerenders whenever the dialog is opened or closed?
<
Yes, I've seen that all the components within App re-render when I click the FAB
I think I understand now. The root App component is re-rendering, so I should use React.memo and useCallback to prevent this, right?
<
That's a valid approach, but there's a simpler way. Let's consider moving the state down the component tree and utilizing component composition to address this. Let's take a look:
const App = () => {
  console.log('other code here')
  return (
    <div className="main">
      <Posts config={configs} data={posts}/>
      <Settings />
      <AdServe id={adId}/>
      <CreatePostModalWithFAB />
    </div>
  );
};
In CreatePostModalWithFAB.tsx:
const CreatePostModalWithFAB = () => {
  const [isModalOpen, setModalOpen] = useState(false);
  return (
    <>
      <FAB
        onClick={() => setModalOpen(true)}
        icon={"lg_plus"}
      />
      { isModalOpen &&
          <Modal onCreated={handleCreatePost}>
            {content}
          </Modal> }
    </>
  );
};
<
I see, we've localized the modal state within the CreatePostModal component. It seems to have resolved the performance issue! Could you explain why this works?
<
Absolutely, there's a bit to unpack here, and it involves going over some core concepts.
Let's look at one of the most important stages of a component that we're interested in when dealing with performance for any react app - the re-rendering phase
Any re-render is triggered from changes done to the state, be it from useState or any state management libraries like mobex.
Take for example our App component
const App = () => {
  const [isModalOpen, setModalOpen] = useState(false);

  return (
    <div>
      <Posts />
      <Settings />
      <AdServe />
      <FAB
        onClick={() => setModalOpen(true)}
      />
      { isModalOpen && <CreatePostModal /> }
    </div>
  );
};
When the FAB is clicked, we use the setModalOpen setter to set isModalOpen to true, after which the App component that has the state re-renders
Once this new state is updated, react then re-renders components like <Posts />, <Settings />, <AdServe /> nested within App until it reaches the end of the component tree.
illustration
The component with the state and its nested components will be re-rendered
illustration2 So if we move the state down to the CreatePostModal component, only that component will re-render when the state changes, and the App component will be unaffected