0

I'm trying to translate a simple button hover example to emca6 (I'm using babel) and keep failing. I guess that my bind is wrong somehow but I'm new to jscript and don't completely understand the:

`

constructor(props) {
        super(props);`

I mean I get that it's like super in python, but why the weird syntax with props passed as parameter?

/* non emca6 */
import React from 'react'

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);


export default HoverButton;

/* emca6 */

import React from 'react';

class HoverButton extends React.Component {
    constructor(props) {
        super(props);
        this.state = ({hover: false});
        this.mouseOver = this.mouseOver.bind(this);
        this.mouseOut = this.mouseOut.bind(this);
    }

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

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


    render() {
        var label = "idle";
        if (this.state.hover) {
            label = "active";
        } 
        return React.createElement(
            "button",
            {onMouseEnter: this.mouseOver, onMouseOut: this.mouseOut},
            label,

        );
    }
}

export default HoverButton;
  • `this.setState = ({hover: true});` -> `this.setState({hover: true});` – Alon Gubkin May 21 '16 at 19:06
  • Thanks that worked, but why? Are we setting the dictionary value without the equal sign because it's in a function? edit: actually it only work once and it doesn't change back to idle and shows a type undefined error on the next hover. – Grumpy Brit May 21 '16 at 19:25
  • setState is method which came from extended React.component class. you cant define like variable. i think Alon should write an answer instead of the comment :) – mkg May 21 '16 at 19:28

2 Answers2

0

I think this should do:

import {Component} from 'react'

class HoverButton extends Component {
    getInitialState: function () {
        return {hover: false};
    },

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

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

    render: function() {
        const label = this.state.hover ? "bar" : "foo";
        return <button 
                  onMouseOver={this.mouseOver.bind(this)}
                  onMouseOut={this.mouseOut.bind(this)}>
                  label
               </button>;
        );
    }
});

Notice the binds on the event handlers. If you would just pass a function like this.mouseOver, it would have the wrong context (this).

Balázs Édes
  • 13,452
  • 6
  • 54
  • 89
  • I've tried the code - after adding a closing "}" at onMouseOver. But I still get a syntax error..? – Grumpy Brit May 21 '16 at 19:43
  • Could you pls paste the error? Possibly in the question? – Balázs Édes May 21 '16 at 19:45
  • Module build failed: SyntaxError: /home/git/studio-branch/assets/js/index.jsx: Unexpected token (4:21) class HoverButton extends Component { getInitialState: function () { return {hover: false}; }, – Grumpy Brit May 21 '16 at 19:59
0

Ok so keeping in mind that I want to write it in emca6 and the answers regarding the right way to bind our state and to assign it, I went with the following.

Although I'm still not completely sure why we bind and assign that way:

import {Component} from 'react'

class HoverButton extends React.Component {
    constructor(props, context) {
        super(props, context);
        this.state = ({hover: false});
    }

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

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


    render() {
        const label = this.state.hover ? "active" : "idle";
        return React.createElement(
            "button",
            {onMouseEnter: this.mouseOver.bind(this), onMouseOut: this.mouseOut.bind(this)},
            label
        );
    }
}

export default HoverButton;

EDIT: So after reading this: Unable to access React instance (this) inside event handler I'm really confused on how to bind the state in the most cost efficient way. Binding it in the constructor doesn't work here.

Edit 2: So I've moved the bind back to the constructor (like it was originally) and its working now for some reason.

import React from 'react'
class HoverButton extends React.Component {
    constructor(props, context) {
        super(props, context);
        this.state = ({hover: false});
        this.mouseOver = this.mouseOver.bind(this);
        this.mouseOut = this.mouseOut.bind(this);
    }

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

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

    render() {
        const label = this.state.hover ? "active" : "idle";
        return React.createElement(
            "button",
            {onMouseEnter: this.mouseOver, onMouseOut: this.mouseOut},
            label
        );
    }
}

export default HoverButton;
Community
  • 1
  • 1
  • You should be able to bind in constructor using `this.mouseOver = this.mouseOver.bind(this)`. Or using class properties you can just define your handlers as fat arrow functions: `mouseOver = (event) => { }` – Aaron Beall May 22 '16 at 02:19