How do you Hover in ReactJS? - onMouseLeave not registered during fast hover over

342,851

Solution 1

Have you tried any of these?

onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp

SyntheticEvent

it also mentions the following:

React normalizes events so that they have consistent properties across different browsers.

The event handlers below are triggered by an event in the bubbling phase. To register an event handler for the capture phase, append Capture to the event name; for example, instead of using onClick, you would use onClickCapture to handle the click event in the capture phase.

Solution 2

The previous answers are pretty confusing. You don't need a react-state to solve this, nor any special external lib. It can be achieved with pure css/sass:

The style:

.hover {
  position: relative;

  &:hover &__no-hover {
    opacity: 0;
  }

  &:hover &__hover {
    opacity: 1;
  }

  &__hover {
    position: absolute;
    top: 0;
    opacity: 0;
  }

  &__no-hover {
    opacity: 1;
  }
}

The React-Component

A simple Hover Pure-Rendering-Function:

const Hover = ({ onHover, children }) => (
    <div className="hover">
        <div className="hover__no-hover">{children}</div>
        <div className="hover__hover">{onHover}</div>
    </div>
)

Usage

Then use it like this:

    <Hover onHover={<div> Show this on hover </div>}>
        <div> Show on no hover </div>
    </Hover>

Solution 3

you can use onMouseOver={this.onToggleOpen} and onMouseOut={this.onToggleOpen} to muse over and out on component

Solution 4

Note: This answer was for a previous version of this question where the question asker was trying to use JavaScript to apply css styles… which can simply be done with CSS.

A simple css-only solution.

For applying basic styles, CSS is simpler and more performant that JS solutions 99% of the time. (Though more modern CSS-in-JS solutions — eg. React Components, etc — are arguably more maintainable.)

Run this code snippet to see it in action…

.hover-button .hover-button--on,
.hover-button:hover .hover-button--off {
  display: none;
}

.hover-button:hover .hover-button--on {
  display: inline;
}
<button class='hover-button'>
  <span class='hover-button--off'>Default</span>
  <span class='hover-button--on'>Hover!</span>
</button>

Solution 5

If you can produce a small demo showing the onMouseEnter / onMouseLeave or onMouseDown / onMouseUp bug, it would be worthwhile to post it to ReactJS's issues page or mailing list, just to raise the question and hear what the developers have to say about it.

In your use case, you seem to imply that CSS :hover and :active states would be enough for your purposes, so I suggest you use them. CSS is orders of magnitude faster and more reliable than Javascript, because it's directly implemented in the browser.

However, :hover and :active states cannot be specified in inline styles. What you can do is assign an ID or a class name to your elements and write your styles either in a stylesheet, if they are somewhat constant in your application, or in a dynamically generated <style> tag.

Here's an example of the latter technique: https://jsfiddle.net/ors1vos9/

Share:
342,851
HelpMeStackOverflowMyOnlyHope
Author by

HelpMeStackOverflowMyOnlyHope

Updated on July 08, 2022

Comments

  • HelpMeStackOverflowMyOnlyHope
    HelpMeStackOverflowMyOnlyHope almost 2 years

    How can you achieve either a hover event or active event in ReactJS when you do inline styling?

    I've found that the onMouseEnter, onMouseLeave approach is buggy, so hoping there is another way to do it.

    Specifically, if you mouse over a component very quickly, only the onMouseEnter event is registered. The onMouseLeave never fires, and thus can't update state... leaving the component to appear as if it still is being hovered over. I've noticed the same thing if you try and mimic the ":active" css pseudo-class. If you click really fast, only the onMouseDown event will register. The onMouseUp event will be ignored... leaving the component appearing active.

    Here is a JSFiddle showing the problem: https://jsfiddle.net/y9swecyu/5/

    Video of JSFiddle with problem: https://vid.me/ZJEO

    The code:

    var Hover = React.createClass({
        getInitialState: function() {
            return {
                hover: false
            };
        },
        onMouseEnterHandler: function() {
            this.setState({
                hover: true
            });
            console.log('enter');
        },
        onMouseLeaveHandler: function() {
            this.setState({
                hover: false
            });
            console.log('leave');
        },
        render: function() {
            var inner = normal;
            if(this.state.hover) {
                inner = hover;
            }
    
            return (
                <div style={outer}>
                    <div style={inner}
                        onMouseEnter={this.onMouseEnterHandler}
                        onMouseLeave={this.onMouseLeaveHandler} >
                        {this.props.children}
                    </div>
                </div>
            );
        }
    });
    
    var outer = {
        height: '120px',
        width: '200px',
        margin: '100px',
        backgroundColor: 'green',
        cursor: 'pointer',
        position: 'relative'
    }
    
    var normal = {
        position: 'absolute',
        top: 0,
        bottom: 0,
        left: 0,
        right: 0,
        backgroundColor: 'red',
        opacity: 0
    }
    
    var hover = {
        position: 'absolute',
        top: 0,
        bottom: 0,
        left: 0,
        right: 0,
        backgroundColor: 'red',
        opacity: 1
    }
    
    React.render(
        <Hover></Hover>,         
        document.getElementById('container')
    )
    
  • Gunchars
    Gunchars over 7 years
    You're showing how to apply a hover CSS effect using inline styles and not how to reliably run code when the cursor is over the element, which is what the user asked for.
  • fkilaiwi
    fkilaiwi over 7 years
    not sure why my answer is not accepted based on that.
  • dreampulse
    dreampulse over 7 years
    This approach won't work, because there is no way to get reliable the onMouseLeave-Event
  • Cory Danielson
    Cory Danielson over 7 years
    Did you check the fiddle? Seems to work fine for me, except that the event is thrown twice when you mouse out.
  • dreampulse
    dreampulse over 7 years
    It will work quite often, but not always! See this discussion: stackoverflow.com/questions/7448468/…
  • trixn
    trixn almost 7 years
    @Gunchars "How can you achieve either a hover event or active event in ReactJS when you do inline styling?". Very first sentence of OP's question. It is pretty much exactly what he asked for.
  • Beau Smith
    Beau Smith almost 6 years
    You might like this answer: stackoverflow.com/a/50342093/101290
  • tsujin
    tsujin almost 6 years
    This does not answer the question.
  • Beau Smith
    Beau Smith almost 6 years
    @tsujin - see the note above.
  • P Fuster
    P Fuster over 5 years
    Just to mention for onMouseEnter and onMouseLeave, from the docs: The onMouseEnter and onMouseLeave events propagate from the element being left to the one being entered instead of ordinary bubbling and do not have a capture phase.
  • Claudiu Creanga
    Claudiu Creanga about 5 years
    more performant that JS solutions 99% of the time not true. read articles debunking this myth. do you have any source?
  • Beau Smith
    Beau Smith about 5 years
    @ClaudiuCreanga - Please link to articles debunking this myth.
  • Claudiu Creanga
    Claudiu Creanga about 5 years
    @BeauSmith developer.mozilla.org/en-US/docs/Web/Performance/… The fact is that, in most cases, the performance of CSS-based animations is almost the same as JavaScripted animations — in Firefox at least. Some JavaScript-based animation libraries, like GSAP and Velocity.JS, even claim that they are able to achieve better performance than native CSS transitions/animations.
  • SmoggeR_js
    SmoggeR_js about 5 years
    It worked perfectly for me, thanks a lot. But, how can I access to that other functions like I for example would exists "onMauseOverFirstTime"? Where did you get that information from?
  • cubefox
    cubefox about 5 years
    @MtgKhaJeskai reactjs.org/docs/events.html If you want sth like onMouseOverFirstTime you'd have to create it yourself, for example, make the function only fire when 'firstMouseOver' in your state is true and set it to false when the function was called once.
  • SmoggeR_js
    SmoggeR_js about 5 years
    I founded! Thank you very much! :D
  • Behnam Eskandari
    Behnam Eskandari about 5 years
    No, it's not exists "onMauseOverFirstTime" function; But you can use a flag to do this action, add this to your states " states :{ isFirstTime:false} " and make it true in "onMouseOver" @MtgKhaJeskai
  • Beau Smith
    Beau Smith about 5 years
    @ClaudiuCreanga - I've clarified the sentence you objected to, to be more concise.
  • Tobia
    Tobia almost 5 years
    @clusterBuddy I suppose it's a bug in JsFiddle or in the libraries, because the code is correct and has always worked fine.
  • Tool
    Tool almost 5 years
    This is the best answer on this question.