React Javascript onclick outside div

18,109

Solution 1

Here is a simple example, I'm using React hooks here instead of classes, but you can use classes too..

The main part is the onClick on the container div, if you run the example below and click on the dialog it won't close it, but clicking on the overlay will.

The e.stopPropagation() on the container div is what stops the events on the contents firing the events on the overlay. Instead of using stopPropagation, another option is checking the target & currentTarget inside the overlay onClick..

const {useState} = React;


function Overlay(props) {
  const {contents} = props;
  const [open, setOpen] = useState(true);
  if (open) {
    return <div className="overlay" onClick={() => setOpen(false)}>
      <div onClick={(e) => {
        //stop clicks getting to the overlay
        e.stopPropagation();
      }}className="overlay-container">
        {contents()}
      </div>
    </div>
  }
  return null;
}


ReactDOM.render(<React.Fragment>
  This is some content to overlay.<br/>
  for testing..
  <Overlay contents={() =>
    <div>This is the contents, clicking here wont effect ovelay</div>
  }/>
</React.Fragment>, document.querySelector('#mount'));
.overlay {
  position: fixed;
  background-color: rgba(100,100,100,0.5);
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
}

.overlay-container {
  border: 1px solid black;
  background-color: white;
  position: absolute;
  top: 30px;
  left: 30px;
  width: 200px;
  height: 80px;
  padding: 5px;
}
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="mount"></div>

Solution 2

You can use a well writen library like this one: react-outside-click-handler

example:

import OutsideClickHandler from 'react-outside-click-handler';

function MyComponent() {
  return (
    <OutsideClickHandler
      onOutsideClick={() => {
        alert('You clicked outside of this component!!!');
      }}
    >
      Hello World
    </OutsideClickHandler>
  );
}

Solution 3

Use react refs https://reactjs.org/docs/refs-and-the-dom.html#creating-refs

You check for the target of the event and use that to show/hide the signout button.

add event listener when component is mounted.

componentWillMount() { document.addEventListener("click", this.handleClickOutside, false); }

remove event listener when component is mounted.

componentWillUnmount() { document.removeEventListener("click", this.handleClickOutside, false); }

do the check for the outside click something like this

handleClickOutside(e) {
    if(this.submitPopoverRef.contains(e.target)) {
        // the click happened in the component
        // code to handle the submit button
        // submit();
        return;
    } 

    // click happened outside the component
    // hide the popover
    this.handleClick(); // set the state false
}

<div ref={node => this.submitPopoverRef = node}> 
... Your code here...

</div>
Share:
18,109
hightides1973
Author by

hightides1973

Currently working with React Framework along with HTML CSS and Javascript. Interested in SQL and database management.

Updated on June 21, 2022

Comments

  • hightides1973
    hightides1973 almost 2 years

    logout with svg icon

    I am working on a website and currently i am having an svg icon for logout. when icon is clicked an overlay is popped up with signout option. when user clicks on signout it should do certain operation and when user clicks outside div overlay should be hidden. i am failing to achieve this.

    i tried to give focus to div by using tabIndex but then signout option is not clickable anymore.

    Header.js

     import React, { Component } from "react";
        import ReactDOM from "react-dom";
        class MainHeader extends React.Component {
          constructor(props) {
            super(props);
            this.state = {
              logOutShown: false
            };
          }
        render() {
        var guiResult = [];
        if (this.state.logOutShown) {
          guiResult.push(
            <div className="Login__Overlay__Frame">
              <div className="User__Login__Overlay">
              <div className="Login__Content" tabIndex="1" onFocus={this.alerting.bind(this)} onBlur={this.toggleOverlay.bind(this)}>Signout</div>
              </div>
            </div>
          );
        }
    
        return (
                <div className="Header__Icon">
                  <div className="Icons__Log__In" tabIndex="0" onClick={this.validate.bind(this)} onBlur={this.toggleOverlay.bind(this)}/>
                  {guiResult}
                </div>
        );
      }
    
      toggleOverlay(){
        console.log("toggle overlay");
        this.setState({ logOutShown: false});
      }
    
      validate() {
        console.log("validate:");
        this.setState(
          {
            logOutShown: true
          }
        );
      }