codegouvfr / react-dsfr

🇫🇷 The Frech Government Design system React toolkit
https://react-dsfr.codegouv.studio
MIT License
403 stars 49 forks source link

open Modal error #245

Closed joelisayas closed 5 months ago

joelisayas commented 5 months ago

Bonjour,

l'ouverture d'une modal via le code myModal.open(), génère régulièrement une erreur

TypeError: Cannot read properties of null (reading 'modal')
at Object.open (Modal.tsx:250:1)

le code :

const myModal = createModal({
  id: 'my-modal',
  isOpenedByDefault: false,
});

const MyComponent = (props: { isActive: boolean; }) => {

  const { isActive } = props;

  useEffect(() => {  
    if (isActive) {   
      myModal.open();
    }
  }, [isActive]);

return (
    <myModal.Component
      title="mon titre"
      iconId="fr-icon-user-heart-line"
    >
      <div>Texte</div>
    </myModal.Component>
  );
};
garronej commented 5 months ago

Hello @joelisayas,

The exception you're reffering to is thrown when you try to open a modal that isn't mounted on the DOM.
If you're trying to open a modal that isn't present on the page it's legitimate to get a runtime exception.
Could you try to reproduce the error in a playground? https://stackblitz.com/edit/nextjs-j2wba3?file=README.md

Thanks

joelisayas commented 5 months ago

that's exactly the problem (not mounted in the dom). So there is a solution ? That's our responsability ?

garronej commented 5 months ago

Well concreately your responsability is to make sure that whenever you call .open() or .close() the Modal component is present in your React tree.

If you share with me your full component and how you're using it I'll be able to tell you how you can adjust your code so this error is prevented.

joelisayas commented 5 months ago

Ok the component is a little bit complex because isActive props is actually a redux slice. looks like this.

const HomePageComponent: React.FC = () => {
  return (
  <>
    <div>Home</>
    <Card title="titre1" />
    <Card title="titre2" />
    <MyComponent />
  </>
  )
}

const myModal = createModal({
  id: 'my-modal',
  isOpenedByDefault: false,
});

const MyComponent: React.FC = () => {
  const isActive = useSelector(isActiveFromRedux);

  useIsModalOpen(myModal, {    
    onConceal: () => {
      console.log('onConceal');
    },
    onDisclose: () => {
      console.log('onDisclose');
    },
  });

  useEffect(() => {  
    if (isActive) {   
      myModal.open();
    }
  }, [isActive]);

  return (
      <myModal.Component
        title="mon titre"
        iconId="fr-icon-user-heart-line"
      >
        <div>Texte</div>
      </myModal.Component>
  );
};

const AnotherComponent: React.FC = () => {
  useEffect(() => {
    if (FormSuccess) {      
      dispatch(setIsActiveFromRedux(true));
      navigate('/homepage');
    }
  }, [submitIsSuccess]);
  return (
  <>

    <div>Another</>
    <form>
    </orm>    
  </>
  )
}

From AnotherComponent we set true to isActiveFromRedux and then navigate to /homepage => HomePageComponent

garronej commented 5 months ago

Unfortunately I can't see anything that could lead to the error mentioned in the piece of code you shared.

Can you share the URL of the repo alongside with some reprodution steps?

joelisayas commented 5 months ago

unfortunately i can't, it's a private repo. I will try to find a solution. Thanks for your time

garronej commented 5 months ago

It's probably not your call but "public money, public code", all code developped by the service public is supposed to be open source.

Regardless, If you want you can use the MUI modal.

If you enable the DSFR MUI integration the look will be very similar from the original modal and it will be a better fit for a fully controlled modal.