skip to Main Content

In this code I am displaying popup that have buttons, when button responsible for cancelation is clicked confirmation dialog shows up. I want the popup to disappear when clicked outside of it so I handle it like so:

  const popupRef = useRef<HTMLDivElement>(null);

  const handleClickOutside = (event: MouseEvent) => {
    if (
      popupRef.current &&
      !popupRef.current.contains(event.target as Node)
    ) {
      onClose();
    }
  };
  

  useEffect(() => {
    document.addEventListener('mousedown', handleClickOutside);

    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };
  }, []);

onClose is callback that closes the popup. Now when button is clicked I create the dialog like so:

      {showCancelConfirmationDialog && 
      <CancelConfirmationDialog 
      onCancel={handleCloseDialog} 
      onConfirm={handleCancelReservation} 
      name={block.lessonWith} 
      time={chosenTime} 
      date={block.day} />}

  const handleCloseDialog = () => {
    console.log("closing");
    setShowCancelConfirmationDialog(false);
  }

  const handleCancelReservation = () => {
    console.log("block")
    block.isReserved = false;
    block.reservedBy = "notMe";
    onClose();
  }

Dialog code:

interface DeleteConfirmationDialogProps {
  onCancel: () => void;
  onConfirm: () => void;
  name: string;
}

const DeleteConfirmationDialog: React.FC<DeleteConfirmationDialogProps> = ({ onCancel, onConfirm, name }) => {
  return (
    <div className="delete-confirmation-dialog">
      <p className='delete-confirmation-dialog-p'>Te jazdy są zarezerwowane przez: {name} </p>
      <p className='delete-confirmation-dialog-p'>Czy na pewno chcesz je przesunąć i powiadomić o tym kursanta?</p>
      <button className='delete-confirmation-dialog-button' onClick={onConfirm}>Usuń i powiadom</button>
      <button className='delete-confirmation-dialog-button' onClick={onCancel}>Anuluj</button>
    </div>
  );
}

export default DeleteConfirmationDialog;

And now the problem is that wherever I click everything disappears because useEffect and handleClickOutside is triggered no matter what and I have no idea what it is happening. If I comment out this code it works fine. I tried adding another popupRef for the dialog but it didn’t work. I also tried to control it via boolean when dialog is active but it also does not work.

3

Answers


  1. Chosen as BEST ANSWER

    I found the answer, Simply add new useRef like so:

      const popupRef = useRef<HTMLDivElement>(null);
      const cancelDialogRef = useRef<HTMLDivElement>(null);
    
      const handleClickOutside = (event: MouseEvent) => {
        if (
          popupRef.current &&
          !popupRef.current.contains(event.target as Node)&&
          !cancelDialogRef.current?.contains(event.target as Node)
        ) {
          onClose();
        }
      };
    
      useEffect(() => {
        document.addEventListener('mousedown', handleClickOutside);
    
        return () => {
          document.removeEventListener('mousedown', handleClickOutside);
        };
      }, []);
    

    and here wrap it into div

          <div ref={cancelDialogRef}>
          {showCancelConfirmationDialog &&
            <CancelConfirmationDialog
              onCancel={handleCloseDialog}
              onConfirm={handleCancelReservation}
              name={block.lessonWith}
              time={chosenTime}
              date={block.day} />}
          </div>
    

    now it works correctly


  2. Maybe the best option would be to use a ready-made component, such as the Dialog of Material-UI.

    You can find more information with good examples here.

    Login or Signup to reply.
  3. I’ve checked your above code.

    I think that there is some issues on this

      const handleClickOutside = (event: MouseEvent) => {
        if (
          popupRef.current &&
          !popupRef.current.contains(event.target as Node)
        ) {
          onClose();
        }
      };
    

    Here is my new code.

    const handleClickOutside = (event: MouseEvent) => {
      if (
         !popupRef.current ||
         popupRef.current.contains(event.target as Node)
       ) {
        return;
      }
      onClose();
    };
    

    Also you need to trigger touchstart event to close modal.

    document.addEventListener('mousedown', handleClickOutside);
    document.addEventListener('touchstart', handleClickOutside);
    
    document.removeEventListener('mousedown', handleClickOutside);
    document.removeEventListener('touchstart', handleClickOutside);
    

    Let me know if you have any still issues.
    I hope that my code is working for you.
    Thank you.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search