如何在创建为样式化组件的自定义 React 模态中检测“onClickOutside”和“onEscapeKeyPress”

How to detect `onClickOutside` and `onEscapeKeyPress` in custom React modal created as a styled component

现在,我已经在这上面花费了大量时间。但是,我无法弄清楚,因为我是使用 styled-components.

的新手

我在 React 中创建了一个 Modal 风格的组件。唯一要做的就是添加 'onClickOutside' 和 'onEscapeKeyPress' 功能。

但是,对于我来说,我无法将事件侦听器添加到 Modal 元素(也无法添加到基础 div 元素)。

Here's a link to codesandbox demo

这是我希望用户使用我的组件的理想方式:

<Modal
    show={this.state.isOpen}
    onBackgroundClick={this.toggleModal}
    onEscapeKeydown={this.toggleModal}
    >
    <Modal.Wrapper>
        <Modal.Header>
            <!-- ignore this -->
        </Modal.Header>
        <Modal.Body>
            <!-- ignore this -->
        </Modal.Body>
        <Modal.Footer>
            <!-- ignore this -->
        </Modal.Footer>
    </Modal.Wrapper>
</Modal>

<Modal
    show={this.state.isOpen}
    closeOnEscape
    closeOnClickOutside
    >
    <Modal.Wrapper>
        <Modal.Header>
            <!-- ignore this -->
        </Modal.Header>
        <Modal.Body>
            <!-- ignore this -->
        </Modal.Body>
        <Modal.Footer>
            <!-- ignore this -->
        </Modal.Footer>
    </Modal.Wrapper>
</Modal>

非常感谢任何帮助。

在等待来自 SO 社区的帮助时,我设法自己找到了解决方案。

简而言之,对于那些像我一样对使用样式化组件比较陌生的人来说:样式化组件就是 'styled' 组件。你不能用任何脚本重载它。为了检测 onClickOutsideonEscapePress,我必须创建一个新的包装器 Modal 组件,它在底层使用 StyledModal 组件。检测按键和鼠标按下的代码就在这里。

这里有一些代码片段来解释我的方法:

Modal.js(片段)

componentDidMount() {
  this.props.closeOnClickOutside &&
    document.addEventListener("mousedown", this.handleClick, false);
  this.props.closeOnEscape &&
    document.addEventListener("keyup", this.handleKeyPress, false);
}
render() {
  return (
    <StyledModal
      style={{ display: this.props.show ? "block" : "none" }}
      ref={this.modal}
    >
      <Wrapper>{this.props.children}</Wrapper>
    </StyledModal>
  );
}

样式化Modal.jsx

import styled from "styled-components";

const StyledModal = styled.div`
  position: fixed;
  padding: 0;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100vh;
  background-color: grey;
  z-index: 1;
`;

export default StyledModal;

index.js(预期用途)

<Modal
  show={this.state.isOpen}
  closeOnEscape
  onClose={() => this.setState({ isOpen: false })}
>
  <Header>I have a nice title</Header>
  <Body>But not much to say...</Body>
  <Footer>
    <button onClick={this.toggleModal}>Cancel</button>
    <button onClick={this.toggleModal}>OK</button>
  </Footer>
</Modal>

Working Demo