Kal
Kal

Reputation: 1774

Reactjs - Toggle dropdown menu on click outside anywhere on page instead of just click on the icon

I have a React js App (No JQuery please) drop down menu that I trigger when the ▼ character is clicked. With my code below, the dropdown menu disappears only when the same ▼ is clicked again. I want to make it disappear when the user clicks anywhere else on the page. How to change the code below to make the dropdown menu disappear when the user clicks anywhere else on the page as well and not just by clicking the same icon ▼ ?

Toggler Icon:

      <span className="show_more" onClick={this.toggleOptions}>
        <MaterialIcon icon="keyboard_arrow_down" />
      </span>

Code for toggling: (used by many components so can the fix be only here ?)

import React, { Component } from 'react'
...
import MaterialIcon from '../icons/material-icon'
import HeaderLogo from './logo'

export default class Header extends Component {
  state = {
    showOptions: false,
  }

  toggleOptions = () => this.setState({ showOptions: !this.state.showOptions })

  render() {
    let { showOptions } = this.state

    return (
      <div className="header">
        <div className="row-container container">
          <div className="col-l">
            <HeaderLogo />
          </div>
          <div className="col-m">
            <Search />
          </div>
          <div className="col-r">
            <div className="header_right">
              <HeaderTopLinks />
              <span className="show_more" onClick={this.toggleOptions}>
                <MaterialIcon icon="keyboard_arrow_down" />
              </span>
            </div>

            {showOptions ? (
              <HeaderOptions toggleOptions={this.toggleOptions} />
            ) : null}
          </div>
        </div>
      </div>
    )
  }
}

Upvotes: 2

Views: 11836

Answers (1)

James
James

Reputation: 5747

The answer can be found here

But to sum it up, you have to listen for clicks on the document, and write a function that will walk the tree and tell you if the click occurred inside or outside your component

Here are the important bits from that link to add to your component:

  handleClickOutside(event) {
    if (this.wrapperRef && !this.wrapperRef.contains(event.target)) {
      alert('You clicked outside of me!');
      this.setState({ showOptions: false });
    }
  }

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

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

  render() {
    let { showOptions } = this.state;

    return <div className="header" ref={(node) => this.setWrapperRef = node}>...all the rest of the component goes here...</div>;
  }

For the record, there are many ways of accomplishing this, this is just one approach.

Upvotes: 3

Related Questions