I have Dropdown which is open by clicking on button and closed on outside click.
This is function which toggle dropdown:
toggleAllCategories = () => {
this.setState({ isOpenAllCategories: !this.state.isOpenAllCategories });
};
That mean by clicking on button you should open and close Dropdown.
But in same time I have implemented with react-refs that click outside of body of dropdown ---> close dropdown.
That make bug - reproduction:
Step 1: Click on "All Categories" btn
Result: Dropdown is open
Step 2: Click again on "All Categories" btn - cus want to close dropdown
Result: As result Dropdown is open.
- Clicked on "All categories" btn (state is changed isOpenAllCategories = true)
HERE is the problem --> 2. Click Again on "All Categories" btn
First is called
handleOutsideClick()function which setsisOpenAllCategories on false.Then is called
toggleAllCategories()which change state on oposite of current valueisOpenAllCategories: !this.state.isOpenAllCategoriesand that istruecushandleOutsideClick()already change state onfalse.
How have toggle dropdown on button click and close on outside click?
All Categories Dropdown component:
class AllCategories extends Component {
componentDidMount() {
document.addEventListener('mousedown', (e) => this.handleClickOutside(e));
}
componentWillUnmount() {
document.removeEventListener('mousedown', (e) => this.handleClickOutside(e));
}
setWrapperRef(node) {
this.wrapperRef = node;
}
handleClickOutside = (event) => {
if (this.wrapperRef && !this.wrapperRef.contains(event.target)) {
this.props.closeAllCategories();
}
};
render() {
return (
<div className="all-categories-wrapper">
<div className="all-categories" ref={(node) => this.setWrapperRef(node)}>
<ul className="all-categories-list">
<li className="all-categories-list-item">All Categories</li>
{this.state.allCategories.map((category) => (
<li
className={`all-categories-list-item ${
category.selected ? 'all-categories-list-item-active' : ''
}`}
>
{category.name}
</li>
))}
</ul>
</div>
</div>
);
}
}
All Categories Button component:
export default ({ toggleAllCategories, className }) => (
<div className="category" onClick={() => toggleAllCategories()} role="button">
<div className={`category-button-wrapper ${className}`}>
<button className="category-button">
Sports <span className="category-button-slash">/</span> Football
</button>
<div className="category-icon-box">
<span className="category-icon">
<i className="material-icons md-30 md-white">expand_more</i>
</span>
</div>
</div>
</div>
);