0

I'm using react google charts and am trying to use the chartEvents method to hook into the selection event.

This works:

const ChartClass = React.createClass({
  getInitialState () {
    return {
      showModal: false
    }
  },
  handleShowModal () {
    this.setState((prev, props) => {
       return {
         showModal: true
       }
    })
  },
  chartEvents: [
    {
      eventName: 'select',
      callback: function (Chart) {
         this.handleShowModal()
      }
    }
  ],
  render () {
    return (
      <Chart
        chartEvents={this.chartEvents}
        data={this.props.data}
      />
    )
  }
})

However within that callback I would like to call some other methods

this.handleOpenModal(ChartObj) // TypeError: this.handleOpenModal is not a function
this.sthElse()

because within this callback this is being set to event itself

console.log(this) //object {eventName: "select", callback: function}

Is there any way to reference the parent class so I can use its methods? I don't think I can simply place the function outside of the class because it needs to use this.setState

1252748
  • 14,597
  • 32
  • 109
  • 229
  • @bergi can you point me to how i can use some of that in my react class please – 1252748 Jun 08 '17 at 22:13
  • You haven't really shown enough of the class code for that, no. – Bergi Jun 08 '17 at 22:14
  • @Bergi Updated. Can you take a look please – 1252748 Jun 08 '17 at 22:20
  • You will need to put the creation of the `chartEvents` in the constructor, where they can be initialised as instance-specific. All the approaches in the duplicate post to bind `this` will work in the constructor scope. – Bergi Jun 08 '17 at 23:14
  • @Bergi I don't believe `React.createClass` has a constructor like `React.Component`... – 1252748 Jun 08 '17 at 23:58
  • Looks like you get to put it inside `getInitialState` then. You can also do it inside `render`, but afaik that's discouraged – Bergi Jun 09 '17 at 00:45
  • @Bergi defining a parameter within `getInitialState` will also make it available only via `this`. And yes, putting it in `render` is def unideal. I believe that closing this question within a few minutes of it being asked was a hasty and unfortunate decision. Are you still certain about it? – 1252748 Jun 09 '17 at 02:13
  • That should work, in `render` you can access it via `this`. But yeah, react is a bit of a special thing, I'll reopen and answer – Bergi Jun 09 '17 at 02:43

2 Answers2

0

React.createClass components did auto-bind all their methods, so you need to do nothing but declare the callback as a method - or just use handleShowModal directly:

const ChartClass = React.createClass({
  getInitialState() {
    return {
      showModal: false
    }
  },
  handleShowModal(Chart) {
    this.setState((prev, props) => {
      return {
        showModal: true
      }
    })
  },
  render() {
    return (
      <Chart
        chartEvents={[
          {
            eventName: 'select',
            callback: this.handleShowModal
          }
        ]}
        data={this.props.data}
      />
    )
  }
})

Of course, given you are using ES6 anyway, you probably should just switch to class syntax.


A (probably considered hacky) alternative would be to create the chartEvents with the bound callback in the getInitialState method:

const ChartClass = React.createClass({
  getInitialState() {
    this.chartEvents = [
      {
        eventName: 'select',
        callback: (Chart) => { // use arrow functions
          this.handleShowModal()
        } // or .bind(this) or whatever here
      }
    ];
    return {
      showModal: false
    }
  },
  handleShowModal () {
    this.setState((prev, props) => {
       return {
         showModal: true
       }
    })
  },
  render () {
    return (
      <Chart
        chartEvents={this.chartEvents}
        data={this.props.data}
      />
    )
  }
})
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
-1

You need to bind "this" in the callback

This can be done by

Using an arrow function

   chartEvents: [
     {
       eventName: 'select',
       callback:  Chart => {
         console.log('component', Chart.chart.getSelection()) //yep, shows the selection
       }
     }
   ],

Binding

   chartEvents: [
     {
       eventName: 'select',
       callback: function (Chart) {
         console.log('component', Chart.chart.getSelection()) //yep, shows the selection
       }.bind(this)
     }
   ],
noveyak
  • 3,240
  • 1
  • 19
  • 19