How to make React animation on Hover?

Nastro picture Nastro · Oct 3, 2018 · Viewed 9.4k times · Source

I need to move menu item underline like in this example.

With jQuery I would do it simply getting left position and width of a menu item. And then perform stop.animation on hover.

I'm trying to do such animation with React. But I can't figure out how to. After google research I found the popular react-motion library for animation. But I can't find the way how to trigger animation on hover.

My task is move blue underline on div hover. Please help me to find the solution.enter image description here

Answer

spirift picture spirift · Oct 3, 2018

You can do this using a css transition and an absolutely positioned stripe for the under line. Then update the left property of the stripe when the element is hovered.

class App extends React.Component {
  constructor() {
    super()
    this.state = {
      left: 0,
    }
  }
  
  handleMouseEnter = (e) => {
    this.setState({
      left: e.target.getBoundingClientRect().x - 8,
    });
  }

  render() {
    return (
      <div className="App">
        <div className="box" onMouseEnter={this.handleMouseEnter} />
        <div className="box" onMouseEnter={this.handleMouseEnter}  />
        <div className="box" onMouseEnter={this.handleMouseEnter}  />
        <div className="box" onMouseEnter={this.handleMouseEnter}  />
        <div className="stripe" style={{ left: this.state.left }}/>
      </div>
    );
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);
.App {
  width: 900px;
  overflow: hidden;
  position: relative;
  padding-bottom: 20px;
}
.box {
  width: 200px;
  height: 200px;
  background: #eee;
  border: 1px solid #333;
  float: left;
  margin-right: 10px;
}
.stripe {
  width: 200px;
  height: 10px;
  background: blue;
  position: absolute;
  bottom: 0;
  transition: left 0.3s;
}
<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="root"></div>

Here is an example on codepen