skip to Main Content

I’d like to close the modal on click outside the modal.

But with the following code the modal closes also when I click on the modal.
It should not close when I click on the modal component.

const useOutsideAlerter = (ref) => {
  useEffect(() => {
    function handleClickOutside(event) {
      if (ref.current && !ref.current.contains(event.target)) {
        alert("You clicked outside of me!");
      }
    }
    document.addEventListener("mousedown", handleClickOutside);
    return () => {
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, [ref]);
};

const NavModal = (props) => {
  const modalOpen = useNavModalStore((state) => state.open);
  const setOpen = useNavModalStore((state) => state.setOpen);

  const wrapperRef = useRef(null);
  useOutsideAlerter(wrapperRef);

  return (
    <div>
      <NavIconButton onClick={setOpen}>
        <Icon src={props.buttonIcon} />
      </NavIconButton>
      <div>
        {modalOpen && (
          <NavModalContent ref={wrapperRef} width={props.modalWidth}>
            {props.children}
          </NavModalContent>
        )}
      </div>
    </div>
  );
};

2

Answers


  1. Why do you want to handle the click outside action in a separate function?

    Have you considered this solution:

    const NavModal = (props) => {
      const modalOpen = useNavModalStore((state) => state.open);
      const setOpen = useNavModalStore((state) => state.setOpen);
      
      const wrapperRef = useRef(null);
    
      useEffect(() => {
        function handleClickOutside(event) {
          if (wrapperRef.current && ! wrapperRef.current.contains(event.target)) {
            alert("You clicked outside of me!");
          }
        }
        document.addEventListener("mousedown", handleClickOutside);
        return () => {
          document.removeEventListener("mousedown", handleClickOutside);
        };
      }, [wrapperRef]);
    
      return (
        <div>
          <NavIconButton onClick={setOpen}>
            <Icon src={props.buttonIcon} />
          </NavIconButton>
          <div>
            {modalOpen && (
              <NavModalContent ref={wrapperRef} width={props.modalWidth}>
                {props.children}
              </NavModalContent>
            )}
          </div>
        </div>
      );
    };
    
    Login or Signup to reply.
  2. refactor like this:

    function useOutsideAlerter(ref, onClick) {
    
      function handleClickOutside(event) {
        if (ref.current && !ref.current.contains(event.target)) {
          alert("You clicked outside of me!");
          onClick();
        }
      }
    
      useEffect(() => {
        document.addEventListener("mousedown", handleClickOutside);
        return () => {
          document.removeEventListener("mousedown", handleClickOutside);
        };
      }, [handleClickOutside]);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search