nice-modal-react icon indicating copy to clipboard operation
nice-modal-react copied to clipboard

Unnecessary re-render when showing multiple modals..

Open sandlz opened this issue 7 months ago • 2 comments

Business description

In my App, there are a lot of modals that need to be displayed, so in some business scenarios, there may be 5 or more modals displayed cascading.

As follows: Modal-A -- Modal-B ------ Modal-C ---------- Modal-D

Code description

Example link

  1. Declare modal constants
export const ModalConstant = {
  modalA: "Modal_A",
  modalB: "Modal_B",
  modalC: "Modal_C",
};

  1. in index.tsx, call register function
NiceModal.register(ModalConstant.modalA, ModalA);
NiceModal.register(ModalConstant.modalB, ModalB);
NiceModal.register(ModalConstant.modalC, ModalC);
  1. in App.tsx
export default function App() {
  console.log("App render");

  const showModalA = () => {
    NiceModal.show(ModalConstant.modalA, {});
  };

  return (
    <div className="App">
      <h1>Muti Modal Re-render demo</h1>
      <Button variant="secondary" onClick={showModalA}>
        Show Modal [A]
      </Button>
    </div>
  );
}
  1. muti modal.tsx
  • Only the title is different
  • In ModalA.tsx, click will show ModalB
  • In ModalB.tsx, click will show ModalC ...
import BootstrapModal from "react-bootstrap/Modal";
import NiceModal, { useModal, bootstrapDialog } from "@ebay/nice-modal-react";
import { ModalConstant } from "../constant";
import Button from "react-bootstrap/Button";

const ModalA = NiceModal.create(() => {
  const modal = useModal();

  console.log("Modal [A] render", `id: ${modal.id}, visible: ${modal.visible}`);
  const showModalB = () => {
    NiceModal.show(ModalConstant.modalB, {});
  };

  return (
    <BootstrapModal {...bootstrapDialog(modal)}>
      <BootstrapModal.Header closeButton>
        <BootstrapModal.Title>Modal A</BootstrapModal.Title>
      </BootstrapModal.Header>

      <BootstrapModal.Body>
        <p>This is modal A.</p>
        <Button variant="secondary" onClick={showModalB}>
          Show Modal [B]
        </Button>
      </BootstrapModal.Body>

      <BootstrapModal.Footer>
        <Button variant="secondary" onClick={modal.hide}>
          Close
        </Button>
        <Button variant="primary" onClick={modal.hide}>
          Save changes
        </Button>
      </BootstrapModal.Footer>
    </BootstrapModal>
  );
});

export default ModalA;

Step

  1. Call showModalA() in App.tsx, it opens the Modal, without re-rendering the App(desired);
  2. Call showModalB() in ModalA.tsx, it opens the Modal B, causes a re-render to the Modal A(not desired).
  3. Call showModalC() in ModalB.tsx, it opens the Modal C, causes a re-render to the Modal A and Modal B(not desired).
  4. Console logs
Modal [A] render id: Modal_A, visible: false
2Modal [A] render id: Modal_A, visible: true
Modal [B] render id: Modal_B, visible: false
Modal [A] render id: Modal_A, visible: true
Modal [B] render id: Modal_B, visible: true
Modal [A] render id: Modal_A, visible: true
Modal [B] render id: Modal_B, visible: true
Modal [C] render id: Modal_C, visible: false
Modal [A] render id: Modal_A, visible: true
Modal [B] render id: Modal_B, visible: true
Modal [C] render id: Modal_C, visible: true

Questions

As you can see, opening the next Modal causes the previous modals re-render.

How can I get around this?

sandlz avatar Jun 25 '24 06:06 sandlz