eBay / nice-modal-react

A modal state manager for React.
https://ebay.github.io/nice-modal-react
MIT License
2.08k stars 120 forks source link

Unnecessary re-render when showing multiple modals.. #162

Open sandlz opened 4 months ago

sandlz commented 4 months ago

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",
    };
2. in `index.tsx`, call register function
```ts
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>
    );
    }
  2. 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)}>

Modal A

This is modal A.

); }); 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 commented 4 months ago

@supnate can you help me? thanks.

jackdunncode commented 2 weeks ago

Hi @sandlz,

I made the same issue a while ago (https://github.com/eBay/nice-modal-react/issues/116), it was resolved but it did not fix the unnecessary re-renders.

My solution, albeit not ideal, was to implement another library (https://github.com/raotaohub/ez-modal-react) to be used as the nested modal.

This prevented re-render on the first modal, which is great. But it's not ideal having 2 libraries that do the same thing..