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>