20
votes

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);
4
It really seems to me that you don't want to create another button.. you probably just want to change the style/behavior of the current button - André Pena
sorry here is my current code: - Widy Gui
i need to know to how to use onMouseEnter function - Widy Gui
@Randy Morris has the correct answer, but why not use JSX (the html-like) syntax for your div and button? - stealthysnacks

4 Answers

45
votes

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/

11
votes

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.

0
votes

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>
-1
votes

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.