3

How to know that user has clicked outside our react app which is pointed to

<div id="root">

(I'm having extra space to click outside root div)

I've tried the below code

import ReactDOM from 'react-dom';
// ... ✂

componentDidMount() {
    document.addEventListener('click', this.handleClickOutside, true);
}

componentWillUnmount() {
    document.removeEventListener('click', this.handleClickOutside, true);
}

handleClickOutside = event => {
    const domNode = ReactDOM.findDOMNode(this);

    if (!domNode || !domNode.contains(event.target)) {
        this.setState({
            visible: false
        });
    console.log("clicked outside")
    }
}

But then, even if I clicked inside some child popup component under parent, it is showing as "clicked outside"

If I click anywhere inside the app (including children component), it should not say, "clicked outside"

So is there any way to know that the user clicked outside the complete app itself?

1

2 Answers 2

1

The easiest way is to set a listener to the application container (the outmost element in the tree), instead of finding the id="root" element.

So, with given index.html:

<div id="root"></div>
<div>Div which outside of app</div>

Possible implementation can be (check the logs):

function useOnClickOutside(ref, handler) {
  useEffect(() => {
    const listener = event => {
      if (!ref.current || ref.current.contains(event.target)) {
        return;
      }

      handler(event);
    };

    document.addEventListener("mousedown", listener);
    document.addEventListener("touchstart", listener);

    return () => {
      document.removeEventListener("mousedown", listener);
      document.removeEventListener("touchstart", listener);
    };
  }, [ref, handler]);
}

const App = () => {
  const divRef = useRef();
  const handler = useCallback(() => console.log(`Click Outside`), []);
  useOnClickOutside(divRef, handler);

  return (
    <div
      ref={divRef}
      style={{
        margin: `0.5rem`,
        padding: `1rem`,
        border: `2px solid black`,
        cursor: `pointer`
      }}
    >
      Application
    </div>
  );
};

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

Edit currying-dust-cpscu

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, but this is not working in my case where one child component is a popup. When we click outside the popup(still inside parent component), it shows "Clicked Outside"
Is is desired behaviour... Clicking on popup is really inside
0

There is a special component, just wrap your component in it and that's it...very convinient

import onClickOutside from "react-onclickoutside";

class MyComponent extends Component {
  handleClickOutside = evt => {
    // ..handling code goes here...
  };
}

export default onClickOutside(MyComponent);

https://github.com/Pomax/react-onclickoutside

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.