0

I'm pretty confident i'm doing this wrong, i'm unable to console.log this.state.greeting however if I reference this.state.greeting inside the return statement it works, i'm confused why it doesn't work within the class method

class Test extends React.Component {

  constructor (props) {
    super(props)
    this.state = {
      greeting: 'test'
    }
  }

  greeting () {
    console.log(this.state.greeting)
  }

  render () {
    return (
      <p onClick={this.greeting}>test</p>
    )
  }

}

export default Test
alilland
  • 2,039
  • 1
  • 21
  • 42

2 Answers2

1

You need to bind it. Here are two options:

class Test extends React.Component {

  constructor (props) {
    super(props)
    this.state = {
      greeting: 'test'
    }
  }

  greeting () {
    console.log(this.state.greeting)
  }

  render () {
    return (
      <p onClick={this.greeting.bind(this)}>test</p>
    )
  }
}

// OR THIS

class Test extends React.Component {

  constructor (props) {
    super(props)
    this.state = {
      greeting: 'test'
    }
    this.greeting = this.greeting.bind(this);
  }

  greeting () {
    console.log(this.state.greeting)
  }

  render () {
    return (
      <p onClick={this.greeting}>test</p>
    )
  }

}
Kousha
  • 32,871
  • 51
  • 172
  • 296
  • your second solution doesnt work, it says `Uncaught TypeError: Cannot read property 'bind' of undefined` – alilland Jan 19 '17 at 19:48
  • You can remove the `bind` call inside `render` here. Once the property is assigned in the constructor, you don't need to bind it again. – Ross Allen Jan 19 '17 at 19:49
  • @alilland: that happens if you have a spelling error (i.e. `this.greeting` does not match the `greeting` function name). Here is a JSFiddle: https://jsfiddle.net/jwm6k66c/1887/ – Kousha Jan 19 '17 at 20:39
  • 1
    @RossAllen You are right. I copied pasted the first example to modify it and forgot to remove the bind – Kousha Jan 19 '17 at 20:39
0

There are actually two tricks to this one. You can either use the bind function in your constructor like so:

this.greeting = this.greeting.bind(this);

or if you have babel setup correctly with es6 and presets then you can do it a better way by using anonymous lambdas. Inside your .babelrc file it should look like this:

{
    "presets": [
        "react",
        "es2015",
        "stage-1"
    ]
}

and have the proper dependencies installed then you can use the es6 functions like this:

class Test extends React.Component {

  constructor (props) {
    super(props);

  }

  greeting = () => {
    console.log(this.state.greeting)
  }

  render = () => {
    return (
      <p onClick={this.greeting}>test</p>
    );
  }

}

export default Test

Personally I love the second option. It doesn't bloat up your constructor, and the anonymous lambdas are nicer to type than function every time.

w9jds
  • 877
  • 6
  • 17
  • i love the sound of #2! Now I wish js-standard didnt complain about it lol – alilland Jan 19 '17 at 21:29
  • 1
    The official term for "anonymous lambda" is *arrow function*. – Felix Kling Jan 19 '17 at 22:09
  • There is a third option as well if you're working in an environment without `stage-2` presets (which is what you need for the [es class fields](https://github.com/tc39/proposal-class-public-fields) you used up there). You can leave the `greeting` method as it is and change the `render` function to return this: `

    this.greeting()}>test

    `.
    – Saad Jan 19 '17 at 22:23