Fabian
Fabian

Reputation: 97

React - Close dropdown menu when clicking on the window

I have a dropdown menu that opens correctly, you can click and it scrolls you to the right section. I also implemented that on clicking on the button again the dropdown will close.

I am now trying to implement that on click outside of the menu the dropdown would also close.

At the moment the best solution I found was to add a click event listener on the window.

This causes a problem which is when you click to open the dropdown, it will directly close it. This is why I added a new state so I can add a condition, but this doesn't work.

Could someone please describe what would be the best way in React to do that ?

Thanks in advance

class Explore extends Component {

constructor(props){
  super(props)

  this.state = {
    visible: false,
    hide: false
  }

  this.whyRef = React.createRef()
  this.overviewRef = React.createRef()

  window.addEventListener('scroll', this.closeMenu);
  // if(this.state.hide === true) window.addEventListener('click', this.closeMenu);
}

toggleMenu = () => {
  if(!this.state.visible){
    this.setState({ visible: true, hide: true });
  } else {
    this.setState({ visible: false, hide: false});
  }
}

closeMenu = () => {
  this.setState({ visible: false });
}

scrollTo = (ref) => {
  window.scrollBy({
      top:ReactDOM.findDOMNode(ref.current).getBoundingClientRect().top - 200,
      behavior: "smooth"   // Optional, adds animation
  })
}

render() {
  const { visible, hide } = this.state

  return (

      <Dropdown
        visible={visible}
        onClick={this.toggleMenu}
        trigger={['click']} overlay={
        <Menu>
          <Menu.Item key="1"
            onClick={() => this.scrollTo(this.whyRef)}>
            <Icon icon={u1F427} /> <strong>WHY</strong>
          </Menu.Item>
          <Menu.Item key="2" onClick={() => this.scrollTo(this.overviewRef)}>
            <Icon icon={u1F30D} /> 30,000 Feet
          </Menu.Item>
        </Menu>
      }>
      <Button style={{display: 'flex', justifyContent: 'center', alignItems: 'center'}}
        size="small">
        <strong className="text-grey clickable">
          <Icon icon={infoCircle} size={14}/> SECTIONS
        </strong>
      </Button>
      </Dropdown>
}                 

Upvotes: 3

Views: 10731

Answers (1)

Edgars Šusts
Edgars Šusts

Reputation: 111

You could try to replace onClick with onFocus to open dropdown and add onBlur for close dropdown. onFocus will trigger when the element is clicked and onBlur will trigger when "unfocusing" (clicking outside). Also tabIndex attribute/prop is needed for focus/blur to work on non input type elements. And i think you are getting state wrong. Replace visible={visible} with visible={this.state.visible} And i removed trigger={['click']} as you commented out eventListener for it.

and code would look something like this:

toggleMenu = () => {
 this.setState({ visible: !this.state.visible });
}

....
....

<Dropdown
  visible={this.state.visible}
  onFocus={this.toggleMenu}
  onBlur={this.toggleMenu}
  tabIndex="0"
  overlay={
  ....
  ....
</Dropdown>

Upvotes: 3

Related Questions