Widy Gui
Widy Gui

Reputation: 221

a hover button in react.js

i would like to ask how to make a button but when the mouse is on the button (hover),the new button is displayed above the previous button... and it's in react.js.. thx

this is the way of my code..

var Category = React.createClass({displayName: 'Category',
  render: function () {
      return (
        React.createElement("div", {className: "row"}, 
        React.createElement("button", null, "Search",   {OnMouseEnter://I have no idea until here})
      )
    );
  }
});

React.render(React.createElement(Category), contain);

Upvotes: 22

Views: 76323

Answers (6)

HiLuLiT
HiLuLiT

Reputation: 553

easy & simple way to do this with hooks:

import React, { useState } from "react";

export default function App() {
  const [hover, setHover] = useState(false);

  const handleMouseIn = () => {
    setHover(true);
  };

  const handleMouseOut = () => {
    setHover(false);
  };

  return (
    <div>
      <button onMouseOver={handleMouseIn} onMouseOut={handleMouseOut}>
        {hover ? "foo" : "bar"}
      </button>
    </div>
  );
}

we have the hover state to track whether we hovered over the button or not. we set it to true in handleMouseIn and false in handleMouseOut. we set onMouseOver to handleMouseIn and onMouseOut to handleMouseOut.

This way, hover is true when we hovered over the button and false otherwise.

Upvotes: 1

Zia Ullah
Zia Ullah

Reputation: 323

Here is my Solution for the Functional Based Components. I'm assuming that you're looking to change the colour of the button on the "mouse hover" event. You can use anything by following my code though.

Please import useState and useEffect hook as

import React, { useState, useEffect } from 'react';

Now, Make the state as:-

const [hover, setHover] = useState(false);

Define the colour that you want to render on Mouse Hover, I'm defining primary colour and mouseOverColor here.

let primaryColor:red
let mouseOverColor:blue

Now in JSX of Reactjs.

return (<div>

<Button
      
      style={backGroundColor: hover === true ? mouseOverColor : primaryColor}
      onMouseOver={(e) => {
        e.preventDefault();
        setHover(true);
      }}
      onMouseLeave={(e) => {
        e.preventDefault();
        setHover(false);
      }}
    >
      Say hi
    </Button>

</div>)

Please make sure to use useEffect dependency with the "hover" property so it should refresh background colour whenever the component gets mouseover effect as:-

  useEffect(() => {}, [hover]);

Note:- I use button of Material UI, you can use plain HTML button too.

import { Button } from '@material-ui/core';

RESULT:- Norammly button would be Red and on Mouse Hover, it should be red and vice versa. That's pretty much it.

Upvotes: 4

Calsal
Calsal

Reputation: 1485

I'm not sure when you would like to show a first button (above) only when the second button is hovered. If the mouse hover is removed from the second button the first button would be disappear again. But I guess the question was to show it and also make it interactable.

In React you would use the state for that. In a functional React component the useState hook is the best option. The onMouseOver event on the button changes the state variable on hover by calling the setShowButtons function. I usually toggle CSS classes based on the variable (showButtons in this example) but one could also use conditional render as button #3 in the this example.

Showing button #1 above when button #2 is hovered is also possible with only CSS. In this example with flex-box (reversing the order of the two buttons) and the sibling selector (~).

const App = () => {
  const [showButtons, setShowButtons] = React.useState(false);
  return (
    <main className="main-container">
      <h4>Show buttons with React state</h4>
      <button className={showButtons ? "button" : "button _hide"}>
        #1. I'm shown with a CSS transition when #2 is hovered
      </button>
      <button
        className="button"
        onMouseOver={() => setShowButtons(true)}
        onFocus={() => setShowButtons(true)}
        onMouseOut={() => setShowButtons(false)}
        onBlur={() => setShowButtons(true)}
      >
        #2. Hover me to show #1 and #3 button
      </button>
      {showButtons && (
        <button className="button">
           #3. I'm rendered when #2 is on hovered
        </button>
      )}
      <hr />
      <h4>Show button with CSS only</h4>
      <div className="reversed-container">
        <button className="button-2">#2. Hover me to show button #1</button>
        <button className="button-2 _hide">
          #1. I'm shown with a CSS transition when #2 is hovered
        </button>
      </div>
    </main>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
.main-container {
  display: flex;
  flex-direction: column;
}

.reversed-container {
  display: flex;
  flex-direction: column-reverse;
}

hr {
  width: 100%;
  margin-top: 1rem;
}

.button,
.button-2 {
  padding: 1rem;
  transition: opacity 1s;
}

.button._hide,
.button-2._hide {
  opacity: 0;
  pointer-events: none;
}


.button:hover,
.button-2:hover {
  opacity: 1;
  pointer-events: initial;
  background-color: lightyellow;
}

.button-2:hover ~ .button-2._hide {
  opacity: 1;
  pointer-events: initial;
  background-color: lightyellow;
}
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>

<div id="root"></div>

Upvotes: 1

vothaison
vothaison

Reputation: 1694

I just read some tutorials about react.js, and I found this solution.

For the sake of reusability, and to separate out the "hover" logic, you can create a component to replace your normal tag.

Something like this:

var React = require('react');
var classNames = require('classnames');
var HoverHandlers = require('./HoverHandlers.jsx');

var ElementHover = React.createClass({
  mixins: [HoverHandlers],

  getInitialState: function () {
    return { hover: false };
  },

  render: function () {
    var hoverClass = this.state.hover ? this.props.hoverClass : '';
    var allClass = classNames(this.props.initialClasses, hoverClass);

    return (
      <this.props.tagName 
                          className={allClass} 
                          onMouseOver={this.mouseOver} 
                          onMouseOut={this.mouseOut}>
        {this.props.children}
      </this.props.tagName>
    );
  }

});

module.exports = ElementHover;

The HoverHandlers mixin is like (you can also add handlers for :active :focus, etc...):

var React = require('react');

var HoverHandlers = {
  mouseOver: function (e) {
    this.setState({ hover: true });
  },
  mouseOut: function (e) {
    this.setState({ hover: false });
  },
};  
module.exports = HoverHandlers;

You then can use the component like this:

<ElementHover tagName="button" hoverClass="hover" initialClasses="btn btn-default" >
          Label or content of the button
</ElementHover>

The code might need to be optimized. So, many thanks to anyone can help me about that.

Upvotes: 0

Randy Morris
Randy Morris

Reputation: 40927

If I understand correctly you're trying to create a whole new button. Why not just change the label/style of the button as @André Pena suggests?

Here is an example:

var HoverButton = React.createClass({
    getInitialState: function () {
        return {hover: false};
    },

    mouseOver: function () {
        this.setState({hover: true});
    },

    mouseOut: function () {
        this.setState({hover: false});
    },

    render: function() {
        var label = "foo";
        if (this.state.hover) {
            label = "bar";
        }
        return React.createElement(
            "button",
            {onMouseOver: this.mouseOver, onMouseOut: this.mouseOut},
            label
        );
    }
});

React.render(React.createElement(HoverButton, null), document.body);

Live demo: http://jsfiddle.net/rz2t224t/2/

Upvotes: 47

Brigand
Brigand

Reputation: 86230

You should probably just use CSS for this, but if you insist on doing it in JS you simply set flag in state to true in your onMouseEnter, and set the same flag to false in onMouseLeave. In render you render the other button if the flag is true.

Nothing fancy or complicated involved.

Upvotes: 12

Related Questions