4

I have a modal reaction component with a button that opens the modal. The modal also has a close button. Here is the code and what the modal looks like:

class Modal extends React.Component {
    static defaultProps = {
        title: "Modal Title",
        float: false,
        color: "pink",
        children: <div>Add children here!</div>
    }

    constructor(props) {
        super(props)
        this.state = {
            show: false
        }
    }

    openModal() {
        this.setState(
            { show: true }
        )
    }

    closeModal() {
        this.setState(
            { show: false }
        );
    }

    render() {
        return (
            <div>
                <button className={"modal-button" + " " + this.props.color} onClick={() => this.openModal()}>{this.props.title}</button>
                {this.state.show && <div className={"modal fade-in" + " " + (this.props.float ? "modal-float" : null)}>
                    <div className="modal-head">
                        <span>{this.props.title}</span>
                        <button id='button' onClick={() => this.closeModal()}>x</button>
                    </div>
                    <div className="modal-body">
                        {this.props.children}
                    </div>
                </div>}
            </div>
        )
    }
}

It has a button that opens the modal. And the modal has a close button too.

I would like close the modal clicking outside. In another question I saw a code like this

handleClick = event => {
    event.preventDefault();

    this.setState({ showModal: true }, () => {
      document.addEventListener("click", this.closeMenu);
    });
  };

closeMenu = () => {
    this.setState({ menuOpen: false }, () => {
      document.removeEventListener('click', this.closeMenu);
    });
  }

But it also close the modal when I click inside the modal.

Sonya
  • 103
  • 2
  • 8
  • Does this answer your question? [How do I detect a click outside an element?](https://stackoverflow.com/questions/152975/how-do-i-detect-a-click-outside-an-element) – lissettdm May 16 '21 at 20:23

1 Answers1

2

You need to add a condition that doesn't close the modal when the modal is open and a click originates inside the modal. To detect where a click is happening, you will probably use refs.

https://reactjs.org/docs/refs-and-the-dom.html

For ex, I added this condition in the closeMenu function:

this.modalRef = React.createRef();

handleClick = event => {
    event.preventDefault();

    this.setState({ showModal: true }, () => {
      document.addEventListener("click", this.closeMenu);
    });
  };

closeMenu = () => {
  if(this.modalRef.current && this.modalRef.current.contains(event.target)) {
    return; 
}
    this.setState({ menuOpen: false }, () => {
      document.removeEventListener('click', this.closeMenu);
    });
  }


render() {
    return (
      <div ref={this.modalRef}>
       // modal component 
      </div>
    );
  }
}

This detects 1. if the modal is open (this.modalRef.current) and 2. if the click originates inside the modal (this.modalRef.current.contains(event.target)), in which case it returns and does not close the modal.

This explains the approach, although it uses hooks not class components, the concept is the same: https://javascript.plainenglish.io/detect-a-click-outside-of-a-react-component-with-a-reusable-hook-and-useref-a0c282171c3f

terraforme
  • 448
  • 4
  • 5