Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make onMouseLeave in React include the child context?

I am currently building a dropdown button to learn React. I have made two onMouseEnter and onMouseLeave events in the parent div to make it visible when hovering it disappear when not. The problem is that those events only stick to parent.

How to make onMouseLeave in React include the child context? Or, how can I keep the state expand be true when hovering on children?

class DropDownButton extends React.Component {
constructor(){
    super();
    this.handleHoverOn = this.handleHoverOn.bind(this);
    this.handleHoverOff = this.handleHoverOff.bind(this);
    this.state = {expand: false};
}

handleHoverOn(){
    if(this.props.hover){
        this.setState({expand: true});
    }
}

handleHoverOff(){
    if(this.props.hover){
        this.setState({expand: false});
    }
}

render() {
    return (
        <div>
            <div className={styles.listTitle}
            onMouseEnter={this.handleHoverOn}
            onMouseLeave={this.handleHoverOff}>
            {this.props.name}
            </div>
            <div>
            {React.Children.map(this.props.children, function(child){
            return React.cloneElement(child, {className: 'child'});
            })}
            </div>
        </div>
     );
}
}
like image 288
Karl Karl Avatar asked Aug 16 '15 14:08

Karl Karl


People also ask

How do you add a hover effect in React?

To show an element on hover in React: Set the onMouseOver and onMouseOut props on the element. Track whether the user is hovering over the element in a state variable. Conditionally render the other element based on the state variable.

What does props with children mean in React?

Props is simply an abbreviation for properties. In React, we utilize props to send data from one component to another (from a parent component to a child component or multiple children components). They come in handy when you want the data flow in an app to be dynamic.

What does React children toArray do?

React. Children. toArray() changes keys to preserve the semantics of nested arrays when flattening lists of children. That is, toArray prefixes each key in the returned array so that each element's key is scoped to the input array containing it.


2 Answers

You have two different divs in your DOM that don't overlap; I'll split up render so it's more obvious:

render() {
    return (
        <div>

            <div className={styles.listTitle}
              onMouseEnter={this.handleHoverOn}
              onMouseLeave={this.handleHoverOff}>
                {this.props.name}
            </div>

            <div>
                {React.Children.map(this.props.children, function(child){
                    return React.cloneElement(child, {className: 'child'});
                })}
            </div>

        </div>
     );
}

The div that has the onMouseLeave attached to it does not contain the children; so, when the mouse moves to hover on a child, it leaves the div and this.handleHoverOff is called.

You might consider using CSS to hide the children if they shouldn't be displayed, or conditionally rendering them:

render() {
    return (
        <div className={styles.listTitle}
          onMouseEnter={this.handleHoverOn}
          onMouseLeave={this.handleHoverOff}>
            {this.props.name}
            {this.state.expanded && this.renderChildren()}
        </div>
     );
},

renderChildren() {
    return (
        <div>
            {React.Children.map(this.props.children, function(child){
                return React.cloneElement(child, {className: 'child'});
            })}
        </div>
    );
}
like image 56
Michelle Tilley Avatar answered Sep 22 '22 07:09

Michelle Tilley


By using the on mouse leave instead of mouse out and blocking the event on the children I got it reliably working no matter how fast I move through my list items.

https://stackoverflow.com/a/18837002/3302764

like image 26
JoshuaTree Avatar answered Sep 22 '22 07:09

JoshuaTree