I have a React app with modal, that pop-ups with rules of the game when one clicks a button. What I want to do is make it so when I click anywhere outside this pop up window it will close. i have three files. app.js, dialog.js, and outsidealerter.js . In my main app.js when I click a button it sets a state to visible, so my element takes it and renders based upon it. my outsideralerer.js basicly detects if there is a click outside anything wrapped with specific tags. Now the problem comes that i have a method that changes the state of visibility in app.js, so in order for outsderalerter.js to use it, I pass it to it so it can have access to my main state and change it so that when a click is outside the zone the pop up window disappears. Kind of works except it closes it down even if i click within a pop up window, because when i pass the value to outsidealerter it considers the whole body as a no click zone. My question is how can I prevent it from triggering and just pass it a value, or is it possible to change the state value of app.js from outsidealerter.js

App.js

 updateState() {
  this.setState({ isOpen: false });
}

<div id='rule-button'>
<button onClick={(e)=>this.setState({isOpen : true})} id="modalBtn" class="button">Open Rules</button>
</div>

<OutsideAlerter updateParent={ this.updateState.bind(this)}/>

<Dialog isOpen={this.state.isOpen} onClose={(e)=>this.setState({isOpen : false})}>
</Dialog>

outsidealerter.js

handleClickOutside(event) {
    if (this.wrapperRef && !this.wrapperRef.contains(event.target)) {
      //alert('You clicked outside of me!');
     {this.props.updateParent()};
    }
  }

1 Answers

0
Asaf Aviv On Best Solutions

I think it will be simpler to have the modal take the full space of the window height and width and just make it invisible except for the content of what you want to show.

We can wrap the modal with onClick={hideModal} and wrap the inner content with onClick={e => e.stopPropagation()} which will prevent our wrapper for triggering the hideModal handler.

class ModalWrapper extends React.Component {
  state = { isModalOpen: true };

  toggleModal = () => {
    this.setState(({ isModalOpen }) => ({
      isModalOpen: !isModalOpen
    }));
  };

  render() {
    const { isModalOpen } = this.state;

    return (
      <div className="App">
        <button onClick={this.toggleModal}>Open Modal</button>
        {isModalOpen && <Modal hideModal={this.toggleModal} />}
      </div>
    );
  }
}

function Modal({ hideModal }) {
  return (
    <div onClick={hideModal} className="modal">
      <div onClick={e => e.stopPropagation()} className="modal__content">
        Modal content
      </div>
    </div>
  );
}

Working example