Home > Mobile >  cannot close modal in react
cannot close modal in react

Time:09-18

I have a modal which opens up when I scan a qr Code. After this I set a props to true which tells my Responsemodal to open up. Problem is, I cannot close because this prop is read-only in child component.

Here is my code:

 const ResponseModal = (props) => {
    const closeIcon = (
      <svg fill="black" width="28" height="28" viewBox="0 0 36 36" data-testid="close-icon"><path d="M28.5 9.62L26.38 7.5 18 15.88 9.62 7.5 7.5 9.62 15.88 18 7.5 26.38l2.12 2.12L18 20.12l8.38 8.38 2.12-2.12L20.12 18z"></path></svg>
    );

    const {flag, data, title} = props;

    const [open, setOpen] = useState(false);
    const onCloseModal = () => setOpen(false);
    
    
    useEffect(() => {
        if(flag == true) {      <--- qr code scanned, this trigger my ResponseModal to open up but it remains true
            setOpen(true);
        }
    })

    return (
      <>
        <Modal open={open} onClose={onCloseModal} center closeIcon={closeIcon} modalId="response-modal">
          <div className="qr-modal-header-stock">
            <h5>Enter stock</h5>
            <p>{title}</p>
          </div>
        </Modal>
      </ >
    );
  }

And my parent component:

const QrScanner = () => {

    const [data, setData ] = useState('');
    const [flag, setFlag] = useState(false);
    const [title, setTitle] = useState('');

    const history = useHistory();
    useEffect(() => {
      if(data === '') {
          return;
      }

        if (Number.isInteger(parseInt(data)))
        { 
            axios.get('/api/qrcodescanner/ean/'   data)
            .then(res => {
                if (res.data.title != false)
                {
                    setFlag(true);
                    setTitle(res.data.title);
                }
                else
                {
                    setData('Sorry, Wrong barcode!');
                }
        })

      }
  })
      return (
         
      <>
          <BarcodeScannerComponent
              width={500}
              height={500}
              onUpdate={(err, result) => {
                  if (result) {
                      setData(result.text);
                  }
              }}
          />
          <p className="modal-result-show">{data}</p>
          <ResponseModal flag={flag} data={data} title={title}/>    
      </>
      );
  }

Even though I set open to false onClose, it dissapears and appears right after, Any thoughts what i'm missing?

CodePudding user response:

You forgot add dependencies in useEffect. Just add flag to dependencies array to make sure it only call when flag change

useEffect(() => {
    if(flag == true) {      <--- qr code scanned, this trigger my ResponseModal to open up but it remains true
        setOpen(true);
    }
}, [flag])

CodePudding user response:

I see you need to expose something back to the parent, there're couple of ways.

open state relocated to the parent.

 const ResponseModal = ({ open, setOpen }) => {
    // currently you use a state, but instead
    // relocate this state to the parent
 }

 const QrScanner = () => {
   const [open, setOpen] = useState(false)

   return <ResponseModal open={open} setOpen={setOpen} />
 }

Basically ask your parent to manage the modal.

listening to the on state

If you think the above approach is too heavy, because you already have a very nice Modal component. We could only build a on flag.

 const ResponseModal = ({ on }) => {
   const [open, setOpen] = useState(on)
   useEffect(() => {
     setOpen(on)
   }, [on])
 }

 const QrScanner = () => {
   const [on, setOn] = useState(false)

   return <ResponseModal on={on} />
 }

This is a trick to make sure on can drive open when changed. In your parent you can just call setOn(false).

I didn't notice you are already using a flag, so that is the on.

  • Related