I use onBlur to close a dropdown, but I also want to handle a click handler of an li which is render within, setState won’t work here, the behavior is broken when user try to open the dropdown again, try it here:
My code:
toggleDropdown = () => {
this.setState({
openDropdown: !this.state.openDropdown
})
}
render() {
return (
<div>
<div tabIndex="0" onFocus={this.toggleDropdown} onBlur={this.toggleDropdown}>
MyList
<ul className={this.state.openDropdown ? 'show' : 'hide'}>
<li>abc</li>
<li>123</li>
<li onClick={()=> this.setState({openDropdown:false})}>xyz</li> {/* not working */}
</ul>
</div>
</div>
);
}
Advertisement
Answer
Your code is not working because, even though you click li, a div container with onBlur event still is focused.
We add to your list container ref, after that we can call .blur(). We use it in your onClick li event handler.
this.dropDownList.blur()
See working example jsfiddle.
Or run this snippet:
class Hello extends React.Component {
constructor() {
super()
this.state = {
isDropdownVisible: false
}
this.toggleDropdown = this.toggleDropdown.bind(this);
}
toggleDropdown() {
this.setState({
isDropdownVisible: !this.state.isDropdownVisible
})
}
render() {
return (
<div>
<div
tabIndex="0"
ref={c => this.dropDownList = c}
onFocus={this.toggleDropdown}
onBlur={this.toggleDropdown}>
MyList
<ul
className={this.state.isDropdownVisible ? 'show' : 'hide'}>
<li>abc</li>
<li>123</li>
<li onClick={() => this.dropDownList.blur()}>xyz</li> {/* not working */}
</ul>
</div>
</div>
);
}
}
ReactDOM.render(
<Hello initialName="World"/>,
document.getElementById('container')
);.hide {
display: none
}
.show {
display: block !important;
}
div:focus {
border: 1px solid #000;
}
div:focus {
outline: none;
}<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id="container"> <!-- This element's contents will be replaced with your component. --> </div>