Modal & Re-renders

In this blog post, we'll delve into managing modals in React. As with any React component, whenever its state changes, the component and all its child components will re-render. This remains true unless a component is memoized, but let's set memoization aside for now.

Let's examine the component below.

  
    import React, { useState } from "react";
    import Modal from "./Components/modal";
    import "./styles.css";

    export default function App() {
    const [showModal, setShowModal] = useState(false);
    const onModalSubmit = () => {
        // logic goes here
        setShowModal(false);
    };

    return (
        <>
        <button onClick={() => setShowModal(true)}>Show Modal</button>
        {showModal && (
            <Modal onCancel={() => setShowModal(false)} onSubmit={onModalSubmit}>
            <p> Are you sure? </p>
            </Modal>
        )}
        {/*  rest of the UI */}
        </>
    );
}
  
Modal Component
  
    import React from "react";

    export default function Modal({ onSubmit, children, onCancel }) {
    return (
        <div className="modal">
        <div className="modal-content">
            {children}
            <div className="modal-footer">
            <button onClick={onSubmit}>Yes</button>
            <button onClick={onCancel}>No</button>
            </div>
        </div>
        </div>
    );
}
  

In many React repositories, you'll commonly encounter this piece of code. The problem lies in the fact that the entire component re-renders every time you open or close the modal. Why does this happen? Well, as soon the state variable showModal changes, it triggers a re-render. While this might be acceptable for not so busy components, it becomes problematic when the component is fetching data from multiple APIs.

Not only does it lead to excessive re-renders, but it also results in multiple requests being sent to the backend server.

This can be verified in below CodeSandbox, click on show modal and check the console,

How to prevent re-renders

As the modal state is controlled by the parent component, We can always move the modal state within modal to mimimize renders, lets refactor this, here's our modal code now

      
    import React, { useState } from "react";

    export default function Modal({ onSubmit, children }) {
    const [showModal, setShowModal] = useState(false);
    const modalSubmit = () => {
        onSubmit();
        setShowModal(false);
    };
    return (
        <>
        <button onClick={() => setShowModal(true)}> Show Modal </button>
        {showModal && (
            <div className="modal">
            <div className="modal-content">
                {children}
                <div className="modal-footer">
                <button onClick={modalSubmit}>Yes</button>
                <button onClick={() => setShowModal(false)}>No</button>
                </div>
            </div>
            </div>
        )}
        </>
    );
    }

  

In the example above, when you click Show Modal, there are no unnecessary re-renders because the modal's state is managed within the Modal component itself. Therefore, if you find your components re-rendering more frequently than needed, it's essential to review how state is handled. Consider whether the state can be moved elsewhere. If so, relocate it to optimize your application and enjoy the benefits of improved performance!