Reputation: 1774
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
Reputation: 5747
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