packages/material-ui/src/ClickAwayListener/ClickAwayListener.js
function ClickAwayListener(props) {
  const { children, mouseEvent = 'onMouseUp', touchEvent = 'onTouchEnd', onClickAway } = props;
  const mountedRef = useMountedRef();
  const movedRef = React.useRef(false);

  const nodeRef = React.useRef(null);
  // can be removed once we drop support for non ref forwarding class components
  const handleOwnRef = React.useCallback(instance => {
    // #StrictMode ready
    nodeRef.current = ReactDOM.findDOMNode(instance);
  }, []);
  const handleRef = useForkRef(children.ref, handleOwnRef);

  const handleClickAway = React.useCallback(
    event => {
      // Ignore events that have been `event.preventDefault()` marked.
      if (event.defaultPrevented) {
        return;
      }

      // IE 11 support, which trigger the handleClickAway even after the unbind
      if (!mountedRef.current) {
        return;
      }

      // Do not act if user performed touchmove
      if (movedRef.current) {
        movedRef.current = false;
        return;
      }

      const { current: node } = nodeRef;
      // The child might render null.
      if (!node) {
        return;
      }

      const doc = ownerDocument(node);

      if (
        doc.documentElement &&
        doc.documentElement.contains(event.target) &&
        !node.contains(event.target)
      ) {
        onClickAway(event);
      }
    },
    [mountedRef, onClickAway],
  );

  const handleTouchMove = React.useCallback(() => {
    movedRef.current = true;
  }, []);

  const listenerProps = {};
  if (mouseEvent !== false) {
    listenerProps[mouseEvent] = handleClickAway;
  }
  if (touchEvent !== false) {
    listenerProps[touchEvent] = handleClickAway;
    listenerProps.onTouchMove = handleTouchMove;
  }

  return (
    <React.Fragment>
      {React.cloneElement(children, { ref: handleRef })}
      <EventListener target="document" {...listenerProps} />
    </React.Fragment>
  );
}
function ClickAwayListener(props) {
  const { children, mouseEvent = 'onMouseUp', touchEvent = 'onTouchEnd', onClickAway } = props;
  const mountedRef = useMountedRef();
  const movedRef = React.useRef(false);

  const nodeRef = React.useRef(null);
  // can be removed once we drop support for non ref forwarding class components
  const handleOwnRef = React.useCallback(instance => {
    // #StrictMode ready
    nodeRef.current = ReactDOM.findDOMNode(instance);
  }, []);
  const handleRef = useForkRef(children.ref, handleOwnRef);

  const handleClickAway = React.useCallback(
    event => {
      // Ignore events that have been `event.preventDefault()` marked.
      if (event.defaultPrevented) {
        return;
      }

      // IE 11 support, which trigger the handleClickAway even after the unbind
      if (!mountedRef.current) {
        return;
      }

      // Do not act if user performed touchmove
      if (movedRef.current) {
        movedRef.current = false;
        return;
      }

      const { current: node } = nodeRef;
      // The child might render null.
      if (!node) {
        return;
      }

      const doc = ownerDocument(node);

      if (
        doc.documentElement &&
        doc.documentElement.contains(event.target) &&
        !node.contains(event.target)
      ) {
        onClickAway(event);
      }
    },
    [mountedRef, onClickAway],
  );

  const handleTouchMove = React.useCallback(() => {
    movedRef.current = true;
  }, []);

  const listenerProps = {};
  if (mouseEvent !== false) {
    listenerProps[mouseEvent] = handleClickAway;
  }
  if (touchEvent !== false) {
    listenerProps[touchEvent] = handleClickAway;
    listenerProps.onTouchMove = handleTouchMove;
  }

  return (
    <React.Fragment>
      {React.cloneElement(children, { ref: handleRef })}
      <EventListener target="document" {...listenerProps} />
    </React.Fragment>
  );
}
function ClickAwayListener ( props ) { const { children , mouseEvent = 'onMouseUp' , touchEvent = 'onTouchEnd' , onClickAway } = props ; const mountedRef = useMountedRef ( ) ; const movedRef = React . useRef ( false ) ; const nodeRef = React . useRef ( null ) ; // can be removed once we drop support for non ref forwarding class components const handleOwnRef = React . useCallback ( instance => { // #StrictMode ready nodeRef . current = ReactDOM . findDOMNode ( instance ) ; } , [ ] ) ; const handleRef = useForkRef ( children . ref , handleOwnRef ) ; const handleClickAway = React . useCallback ( event => { // Ignore events that have been `event.preventDefault()` marked. if ( event . defaultPrevented ) { return ; } // IE 11 support, which trigger the handleClickAway even after the unbind if ( ! mountedRef . current ) { return ; } // Do not act if user performed touchmove if ( movedRef . current ) { movedRef . current = false ; return ; } const { current : node } = nodeRef ; // The child might render null. if ( ! node ) { return ; } const doc = ownerDocument ( node ) ; if ( doc . documentElement && doc . documentElement . contains ( event . target ) && ! node . contains ( event . target ) ) { onClickAway ( event ) ; } } , [ mountedRef , onClickAway ] , ) ; const handleTouchMove = React . useCallback ( ( ) => { movedRef . current = true ; } , [ ] ) ; const listenerProps = { } ; if ( mouseEvent !== false ) { listenerProps [ mouseEvent ] = handleClickAway ; } if ( touchEvent !== false ) { listenerProps [ touchEvent ] = handleClickAway ; listenerProps . onTouchMove = handleTouchMove ; } return ( < React . Fragment > { React . cloneElement ( children , { ref : handleRef } ) } < EventListener target = "document" { ... listenerProps } / > < / React . Fragment > ) ; }
Listen for click events that occur somewhere in the document, outside of the element itself.
For instance, if you need to hide a menu when people click anywhere else on your page.
Listen for click events that occur somewhere in the document outside of the element itself . For instance if you need to hide a menu when people click anywhere else on your page .