Reputation: 558
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.
HERE is the problem --> 2. Click Again on "All Categories" btn
First is called handleOutsideClick()
function which sets isOpenAllCategories on false
.
Then is called toggleAllCategories()
which change state on oposite of current value isOpenAllCategories: !this.state.isOpenAllCategories
and that is true
cus handleOutsideClick()
already change state on false
.
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>
);
Upvotes: 0
Views: 385
Reputation: 736
Code isn't working because of the scope of this in your component functions. You'll have to bind your functions in the constructor of your component. Or change your functions to ES6 which will solve the issue
//binding
constructor(props){
super(props)
this.handleClickOutside = this.handleClickOutside.bind(this);
}
handleClickOutside = () => {
//code here
}
Upvotes: 1