简体   繁体   English

React Modal 仅在我单击背景或关闭图标时关闭?

[英]React Modal only close when I click background or close icon?

Here is a codepenhttps://codesandbox.io/s/amazing-morning-ukxp2?file=/src/App.js这是一个代码笔https://codesandbox.io/s/amazing-morning-ukxp2?file=/src/App.js

So I created this modal and I wrapped it with a Background styled component, but I can't figure out how to get the close function to only work if I only click the background or the close icon.所以我创建了这个模式,并用Background样式的组件包装它,但我无法弄清楚如何让关闭功能仅在我只单击背景或关闭图标时才起作用。

Right now my entire modal is wrapped with this background so no matter where I click it always closes.现在我的整个模式都被这个background包裹着,所以无论我点击哪里它总是关闭。 I only want it to close if I click on the Background or the CloseModalButton , but not when I click on my actual modal.我只希望它在单击BackgroundCloseModalButton时关闭,而不是在单击我的实际模式时关闭。

Here is my code below下面是我的代码

      export const Modal = ({ showModal, setShowModal }) => {
        const animation = useSpring({
          opacity: showModal ? 1 : 0,
          transform: showModal ? `translateY(0%)` : `translateY(-200%)`
        });

        return (
          <>
            {showModal ? (
              <Background onClick={() => setShowModal(!showModal)}>
                <animated.div style={animation}>
                  <ModalWrapper showModal={showModal}>
                    <div>hi</div>
                    <CloseModalButton
                      aria-label='Close modal'
                      onClick={() => setShowModal(!showModal)}
                    />
                  </ModalWrapper>
                </animated.div>
              </Background>
            ) : null}
          </>
        );
      };

Then here is my App.js with the function to open and close the modal然后这是我的 App.js,具有打开和关闭模式的功能

    function App() {
      const [showModal, setShowModal] = useState(false);

      const openModal = () => {
        setShowModal(!showModal);
      };

      return (
        <Container>
          <Button onClick={openModal}>Aye what's good</Button>
          <Modal showModal={showModal} setShowModal={setShowModal} />
          <GlobalStyle />
        </Container>
      );
    }

The main issue is the Background wraps my entire modal, so I need a way to only trigger my close function if the target is the actually background or the X icon, but not the actual modal itself (which is wrapped inside of the background)主要问题是背景包裹了我的整个模态,所以我需要一种方法来仅在目标是实际背景或 X 图标时触发我的关闭功能,而不是实际模态本身(包裹在背景内)

You need to track event.target which gives where is has been called ie您需要跟踪event.target ,它给出了被调用的位置,即

const closeModal = (event) => {
    const modal = document.getElementById("myModal");
    if (event.target === modal) {
      setShowModal(false);
    }
  };
<Background id="myModal" onClick={closeModal}>

Here is the demo: https://codesandbox.io/s/cranky-hodgkin-o77em?file=/src/components/Modal.js这是演示: https : //codesandbox.io/s/cranky-hodgkin-o77em?file=/ src/components/ Modal.js

The problem is due to event bubbling.问题是由于事件冒泡。 Everytime you click any descendants of the Background element, the click handlers of them fires and bubbles up until it reaches the Background element firing the handler of itself.每次单击Background元素的任何后代时,它们的单击处理程序都会触发并冒泡,直到到达 Background 元素触发其自身的处理程序。 To solve this, you can either stop the propagation of the click handler of the child elements using stopPropagation() method or you can simply add ID to background and determine if the id matches the background only then firing the showModal method.为了解决这个问题,您可以使用 stopPropagation() 方法停止子元素的单击处理程序的传播,或者您可以简单地将ID添加到背景并确定ID是否与背景匹配,然后才触发 showModal 方法。

<Background onClick={closeModal} id="bg">

const closeModal = (e) => {
    if (e.target.id === 'bg') {
      setShowModal(false);
    }
  };

It is not necessary to add id to the close button and check for the targeted button's id since clicking on the button definitely closes the modal.没有必要将 id 添加到关闭按钮并检查目标按钮的 id,因为单击按钮肯定会关闭模式。

I seen an comment asking how to achieve this with useRef (included typescript types):我看到一条评论询问如何使用 useRef (包括打字稿类型)实现这一点:

const modalBackgroundRef = useRef<HTMLDivElement>(null);

const closeModal = () => {
    // Close the modal...
};

const onClickBackground = (event: MouseEvent<HTMLDivElement>) => {
    if (event.target === modalBackgroundRef.current) closeModal();
};

return (
    <div id="modal-background" tabIndex={-1} ref={modalBackgroundRef} onClick={onClickBackground}>
          // Modal goes here...
    </div>
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM