0

I'm getting data from an API but I cant seem to get an onClick listener to work with the returned results

  async componentDidMount() {
    const response = await fetch('/api/mediabuys');
    await response.json().then(data => {
      let markets = data.mediabuys.map(function(item)  {
        return(
          <tr key={item.id}>
            <td onClick={this.openWindow.bind(this)}>{item.name}</td>
          </tr>
        )
      })
      this.setState({markets: markets});
    })
  }

  openWindow() {
    console.log('a');
  }

and the error im getting is:

Uncaught (in promise) TypeError: Cannot read property 'openWindow' of undefined

if I add in this.openWindow to the beginning of ComponentDidMount, its able to run the function and I also have this.openWindow = this.openWindow.bind(this) in the constructor. How can I get the onClick to see the function?

qaakmnd
  • 339
  • 2
  • 4
  • 18
  • You should store data.mediaBuys in state instead of jsx and then map that data in render function, that will be better approach – Abhay Sehgal Aug 29 '18 at 15:12

4 Answers4

1

change

 function(item)  {

to

 item => {

to prevent loosing context.

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
1

It's because you're currently binding to the local scope. Change:

function(item)  {

To:

(item) => {

The arrow function will allow you to access the parent scope.

Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231
0

You don't need to bind this twice, so it's enough to just pass this.openWindow to the onClick attribute. https://reactjs.org/docs/handling-events.html Also function literal will not bind this so you need to use the new arrow syntax to pass a function for the map.

Adam Nagy
  • 77
  • 10
0

Bind the anonymous function you passed to .map with this. Or use an Arrow function.

let markets = data.mediabuys.map(function (item) {
  return (
    <tr key={item.id}>
      <td onClick={this.openWindow}>{item.name}</td>
    </tr>
  )
}.bind(this))

Or,

let markets = data.mediabuys.map( (item) => {
  return (
    <tr key={item.id}>
      <td onClick={this.openWindow}>{item.name}</td>
    </tr>
  )
})

Both way, function passed to the map function will have access to the outer context this.

Arup Rakshit
  • 116,827
  • 30
  • 260
  • 317