GonFreecss
GonFreecss

Reputation: 5

Pure Javascript mouseenter and mouseleave event delegation with React issues

I would like to achieve something like this on my React project (https://creativesfeed.com/code/custom-cursors/index2.html)

I want to have a custom mouse cursor (a dot in this case which is in a "div") which follows the coordinates the mouse and that's fine, I can make it work.

The other thing that I want to achieve is that when hovering on ANY tag, a custom class will be added to the custom mouse cursor and removed when the custom cursor leave the link. The problem is that whenever I hover on the tag, the class appear and disappear immediately. I know that eventListener in Javascript are different from jQuery and I even tried with jQuery (which I hate to have in React) and I have the same issue. So what am I doing wrong? Could it be because I run the function on componentDidMount() ?

import React, { Component } from 'react';
import Homepage from './components/Homepage';

class App extends Component {

  componentDidMount() {
    let mouse__follower = document.getElementById('mouse__follower');
    let links = document.getElementsByTagName('a');

    document.addEventListener("mousemove", (e) => {
      var x = e.clientX;
      var y = e.clientY;
      mouse__follower.style.top = `${y}px`;
      mouse__follower.style.left = `${x}px`;
    });

    let addClassToLink = (e) => {
      mouse__follower.classList.add('active');
    };

    let removeClassToLink = (e) => {
      mouse__follower.classList.remove('active');
    };

    // ALSO, IS THIS VERY BAD IN TERMS OF MEMORY CONSUMING?

    for(var i = 0, len = links.length; i < len; i++) {
      links[i].addEventListener('mouseenter', addClassToLink, false);
      links[i].addEventListener('mouseleave', removeClassToLink, false);
    };

  }

  render() {
    return (
      <div className="nu-creative">
        <div id="mouse__follower">
          <div id="mouse__follower__circle"></div>
        </div>
        <Homepage />
      </div>
    );
  }
}

export default App;

The link is in another file, but I think that's not the issue.

EDIT: I have found the issue. If I remove

mouse__follower.style.top = `${y}px`;
mouse__follower.style.left = `${x}px`;

from the document.addEventListener("mousemove", ...) the class is added and removed correctly, so there's must something there that I can do. Maybe is because two eventListener are triggered together.

I will investigate, thanks for the answers so far :)

Upvotes: 0

Views: 418

Answers (2)

GonFreecss
GonFreecss

Reputation: 5

ISSUES SOLVED :)

The z-index of the div containing the "dot" wasn't set and this was causing the event to trigger too many times. By setting the "z-index" to -1 the issues was solved.

Upvotes: 0

Mark E
Mark E

Reputation: 3483

Looks like the react life cycle is messing around with you. The thing is that react re-renders the html whenever it decides it should be done, and in your render method you are removing the inline classes.

So, the way to do this react-wise would be to set a flag in the state of your component which you change with setState, and check for this flag in your render method to decide wether or not add the class to the cursor.

Something like this:
<div id="mouse__follower" className={this.state.cursorActive? "active":""}>

Edit:
btw, this is not related but, remember to unbind all your event listeners that were bound in componentDidMount inside the componentWillUnmount.

Upvotes: 2

Related Questions