Hoe zweef je in ReactJS? – onMouseLeave niet geregistreerd tijdens snelle muisaanwijzer

Hoe kun je een hover-evenement of een actief evenement in ReactJS bereiken als je inline styling doet?

Ik heb ontdekt dat de onMouseEnter, onMouseLeave-aanpak fouten bevat, dus ik hoop dat er een andere manier is om het te doen.

In het bijzonder, als u heel snel met de muis over een component gaat, wordt alleen de gebeurtenis onMouseEnter geregistreerd. De onMouseLeave wordt nooit geactiveerd en kan dus de status niet bijwerken… waardoor het lijkt alsof de component er nog steeds overheen zweeft. Ik heb hetzelfde opgemerkt als je probeert de “:active” css pseudo-klasse na te bootsen. Als je heel snel klikt, wordt alleen de gebeurtenis onMouseDown geregistreerd. De gebeurtenis onMouseUp wordt genegeerd… waardoor de component actief blijft.

Hier is een JSFiddle die het probleem laat zien: https://jsfiddle.net/y9swecyu/5/

Video van JSFiddle met probleem: https://vid.me/ZJEO

De 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')
)

Antwoord 1, autoriteit 100%

Heb je een van deze geprobeerd?

onMouseDown onMouseEnter onMouseLeave
onMouseMove onMouseOut onMouseOver onMouseUp

SyntheticEvent

het vermeldt ook het volgende:

React normaliseert gebeurtenissen zodat ze consistente eigenschappen hebben in verschillende browsers.

De onderstaande event-handlers worden geactiveerd door een event in de bubbelfase. Om een ​​event-handler voor de capture-fase te registreren, voegt u Capture toe aan de eventnaam; in plaats van onClick te gebruiken, zou u bijvoorbeeld onClickCapture gebruiken om de klikgebeurtenis in de vastlegfase af te handelen.


Antwoord 2, autoriteit 38%

De vorige antwoorden zijn behoorlijk verwarrend. Je hebt geen react-state nodig om dit op te lossen, noch een speciale externe lib. Het kan worden bereikt met pure css/sass:

De stijl:

.hover {
  position: relative;
  &:hover &__no-hover {
    opacity: 0;
  }
  &:hover &__hover {
    opacity: 1;
  }
  &__hover {
    position: absolute;
    top: 0;
    opacity: 0;
  }
  &__no-hover {
    opacity: 1;
  }
}

De reactiecomponent

Een simpele hoverPure-Rendering-functie:

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

Gebruik

Gebruik het dan als volgt:

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

Antwoord 3, autoriteit 22%

u kunt onMouseOver={this.onToggleOpen}en onMouseOut={this.onToggleOpen}gebruiken om over en uit te mijmeren over component


Antwoord 4, autoriteit 14%

Opmerking:dit antwoord was voor een eerdere versie van deze vraag waarbij de vraagsteller JavaScript probeerde te gebruiken om CSS-stijlen toe te passen… wat eenvoudig kan worden gedaan met CSS.

Een simpele CSS-only oplossing.

Voor het toepassen van basisstijlen is CSS 99% van de tijd eenvoudiger en performanter dan JS-oplossingen. (Hoewel modernere CSS-in-JS-oplossingen – bijv. React Components, enz. – aantoonbaar beter te onderhouden zijn.)

Voer dit codefragment uit om het in actie te zien…

.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>

Snippet uitvouwen


Antwoord 5, autoriteit 10%

Als je een kleine demo kunt maken met de bug onMouseEnter / onMouseLeave of onMouseDown / onMouseUp, zou het de moeite waard zijn om deze op de problemenpagina of mailinglijst van ReactJS te plaatsen, gewoon om de vraag te stellen en te horen wat de ontwikkelaars te zeggen hebben het.

In uw gebruik lijkt u te suggereren dat CSS :hover en :active staten voldoende zouden zijn voor uw doeleinden, dus ik raad u aan ze te gebruiken. CSS is orden van grootte sneller en betrouwbaarder dan Javascript, omdat het direct in de browser wordt geïmplementeerd.

De statussen :hover en :active kunnen echter niet worden opgegeven in inline-stijlen. Wat u kunt doen is een ID of een klassenaam toewijzen aan uw elementen en uw stijlen schrijven in een stylesheet, als ze enigszins constant zijn in uw toepassing, of in een dynamisch gegenereerde <style>-tag .

Hier is een voorbeeld van de laatste techniek: https://jsfiddle.net/ors1vos9/


Antwoord 6, autoriteit 8%

Ik ben net hetzelfde probleem tegengekomen bij het luisteren naar onMouseLeave-gebeurtenissen op een uitgeschakelde knop. Ik heb er omheen gewerkt door te luisteren naar de native mouseleave-gebeurtenis op een element dat de uitgeschakelde knop omhult.

componentDidMount() {
    this.watchForNativeMouseLeave();
},
componentDidUpdate() {
    this.watchForNativeMouseLeave();
},
// onMouseLeave doesn't work well on disabled elements
// https://github.com/facebook/react/issues/4251
watchForNativeMouseLeave() {
    this.refs.hoverElement.addEventListener('mouseleave', () => {
        if (this.props.disabled) {
            this.handleMouseOut();
        }
    });
},
render() {
    return (
        <span ref='hoverElement'
            onMouseEnter={this.handleMouseEnter}
            onMouseLeave={this.handleMouseLeave}
        >
            <button disabled={this.props.disabled}>Submit</button>
        </span>
    );
}

Hier is een viool https://jsfiddle.net/qfLzkz5x/8/


Antwoord 7, autoriteit 5%

Ik zou onMouseOver & opMouseOut. Oorzaak in Reageren:

De gebeurtenissen onMouseEnter en onMouseLeave planten zich voort van het element dat wordt overgelaten naar het element dat wordt ingevoerd in plaats van gewoon bubbelen en hebben geen opnamefase.

Hier staat het in de React documentatievoor muisgebeurtenissen.


Antwoord 8, autoriteit 3%

Een pakket genaamd styled-componentskan dit probleem op een ELEGANTEmanier oplossen.

Referentie

  1. Glen Maddern – Styling van React-apps met gestileerde componenten

Voorbeeld

const styled = styled.default
const Square = styled.div`
  height: 120px;
  width: 200px;
  margin: 100px;
  background-color: green;
  cursor: pointer;
  position: relative;
  &:hover {
    background-color: red;
  };
`
class Application extends React.Component {
  render() {
    return (
      <Square>
      </Square>
    )
  }
}
/*
 * Render the above component into the div#app
 */
ReactDOM.render(<Application />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js"></script>
<script src="https://unpkg.com/styled-components/dist/styled-components.min.js"></script>
<div id='app'></div>

Snippet uitvouwen


Antwoord 9, autoriteit 2%

Met inline styling alleen red je het niet. Het is niet aan te raden om CSS-functies opnieuw te implementeren in JavaScript. We hebben al een taal die extreem krachtig en ongelooflijk snel is gebouwd voor dit gebruik: CSS. Maak er dus gebruik van! Style Itgemaakt om te helpen.

npm install style-it --save

Functionele syntaxis(JSFIDDLE)

import React from 'react';
import Style from 'style-it';
class Intro extends React.Component {
  render() {
    return Style.it(`
      .intro:hover {
        color: red;
      }
    `,
      <p className="intro">CSS-in-JS made simple -- just Style It.</p>
    );
  }
}
export default Intro;

JSX-syntaxis(JSFIDDLE)

import React from 'react';
import Style from 'style-it';
class Intro extends React.Component {
  render() {
    return (
      <Style>
      {`
        .intro:hover {
          color: red;
        }
      `}
      <p className="intro">CSS-in-JS made simple -- just Style It.</p>
    </Style>
  }
}
export default Intro;

Antwoord 10

Gebruik Radium!

Het volgende is een voorbeeld van hun website:

var Radium = require('radium');
var React = require('react');
var color = require('color');
@Radium
class Button extends React.Component {
  static propTypes = {
    kind: React.PropTypes.oneOf(['primary', 'warning']).isRequired
  };
  render() {
    // Radium extends the style attribute to accept an array. It will merge
    // the styles in order. We use this feature here to apply the primary
    // or warning styles depending on the value of the `kind` prop. Since its
    // all just JavaScript, you can use whatever logic you want to decide which
    // styles are applied (props, state, context, etc).
    return (
      <button
        style={[
          styles.base,
          styles[this.props.kind]
        ]}>
        {this.props.children}
      </button>
    );
  }
}
// You can create your style objects dynamically or share them for
// every instance of the component.
var styles = {
  base: {
    color: '#fff',
    // Adding interactive state couldn't be easier! Add a special key to your
    // style object (:hover, :focus, :active, or @media) with the additional rules.
    ':hover': {
      background: color('#0074d9').lighten(0.2).hexString()
    }
  },
  primary: {
    background: '#0074D9'
  },
  warning: {
    background: '#FF4136'
  }
};

Snippet uitvouwen


Antwoord 11

Ik had een soortgelijk probleem toen onMouseEnter werd aangeroepen, maar soms werd de bijbehorende onMouseLeave-gebeurtenis niet geactiveerd, hier is een tijdelijke oplossing die goed voor mij werkt (het is gedeeltelijk afhankelijk van jQuery):

var Hover = React.createClass({
    getInitialState: function() {
        return {
            hover: false
        };
    },
    onMouseEnterHandler: function(e) {
        this.setState({
            hover: true
        });
        console.log('enter');
        $(e.currentTarget).one("mouseleave", function (e) {
            this.onMouseLeaveHandler();
        }.bind(this));
    },
    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} >
                    {this.props.children}
                </div>
            </div>
        );
    }
});

Zie op jsfiddle: http://jsfiddle.net/qtbr5cg6/1/


Waarom gebeurde het (in mijn geval): ik voer een jQuery-scrollanimatie uit (via $('#item').animate({ scrollTop: 0 })) wanneer klikken op het artikel. Dus de cursor verlaat het item niet “natuurlijk”, maar tijdens een JavaScript-gestuurde animatie … en in dit geval is de onMouseLeave niet correct geactiveerd door React (React 15.3.0, Chrome 51, Desktop)


Antwoord 12

Ik weet dat het een tijdje geleden is dat deze vraag werd gesteld, maar ik loop tegen hetzelfde probleem aan van inconsistentie met onMouseLeave()
Wat ik deed, is onMouseOut() gebruiken voor de vervolgkeuzelijst en bij muisverlof voor het hele menu, het is betrouwbaar en werkt elke keer dat ik het heb getest.
Ik zag de gebeurtenissen hier in de documenten: https://facebook.github .io/react/docs/events.html#mouse-events
hier is een voorbeeld met https://www.w3schools.com/bootstrap/bootstrap_dropdowns.asp:

handleHoverOff(event){
  //do what ever, for example I use it to collapse the dropdown
  let collapsing = true;
  this.setState({dropDownCollapsed : collapsing });
}
render{
  return(
    <div class="dropdown" onMouseLeave={this.handleHoverOff.bind(this)}>
      <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Dropdown Example
      <span class="caret"></span></button>
      <ul class="dropdown-menu" onMouseOut={this.handleHoverOff.bind(this)}>
        <li><a href="#">bla bla 1</a></li>
        <li><a href="#">bla bla 2</a></li>
        <li><a href="#">bla bla 3</a></li>
      </ul>
    </div>
  )
}

Antwoord 13

Ik gebruik persoonlijk Style Itvoor inline-stijl in React of bewaar mijn stijl apart in een CSS– of SASS-bestand…

Maar als je echt geïnteresseerd bent om het inline te doen, kijk dan eens in de bibliotheek, ik deel hieronder enkele van de toepassingen:

In de component:

import React from 'react';
import Style from 'style-it';
class Intro extends React.Component {
  render() {
    return (
      <Style>
        {`
          .intro {
            font-size: 40px;
          }
        `}
        <p className="intro">CSS-in-JS made simple -- just Style It.</p>
      </Style>
    );
  }
}
export default Intro;

Uitvoer:

   <p class="intro _scoped-1">
      <style type="text/css">
        ._scoped-1.intro {
          font-size: 40px;
        }
      </style>
      CSS-in-JS made simple -- just Style It.
    </p>

U kunt ook JavaScript-variabelen gebruiken met hover in uw CSS, zoals hieronder:

import React from 'react';
import Style from 'style-it';
class Intro extends React.Component {
  render() {
    const fontSize = 13;
    return Style.it(`
      .intro {
        font-size: ${ fontSize }px;  // ES2015 & ES6 Template Literal string interpolation
      }
      .package {
        color: blue;
      }
      .package:hover {
        color: aqua;
      }
    `,
      <p className="intro">CSS-in-JS made simple -- just Style It.</p>
    );
  }
}
export default Intro;

En het resultaat zoals hieronder:

<p class="intro _scoped-1">
  <style type="text/css">
    ._scoped-1.intro {
      font-size: 13px;
    }
    ._scoped-1 .package {
      color: blue;
    }
    ._scoped-1 .package:hover {
      color: aqua;
    }
  </style>
  CSS-in-JS made simple -- just Style It.
</p>

Antwoord 14

Hover is een CSS-functie; het wordt geleverd met de CSS-kant van de app, dus doe het op de juiste manier is zo leuk. Simpel gezegd, wanneer ik een hover-effect op een element in de React-app nodig heb, maak ik eerst een klasse in mijn CSS-bestand en voeg ik vervolgens de gemaakte klasse toe aan de className van het element. De stappen die ik volg zijn:

  1. Maak een CSS-bestand tenzij u index.css

    heeft

  2. Maak een klas met een hoverpseudo-klasse ingeschakeld

    .hover__effect:hover {}

  3. Voeg de gewenste effecten toe

    .hover__effect:hover {
    achtergrondkleur: rgb(255, 255, 255);
    kleur: rgb(0, 0, 0);
    }

  4. Voeg vervolgens het hover__effecttoe aan de klasse-component die anders zou moeten zijn als de muisaanwijzer erover beweegt

    Hover

Controleer mijn sandboxvoor een live demo.

Other episodes