javascript - React - this is undefined when binding function to component - Stack Overflow

I have this code. I imported some ponents from Semantic UI.import React from 'react'import {

I have this code. I imported some ponents from Semantic UI.

import React from 'react'
import { Card, Image, Grid } from 'semantic-ui-react'

I am trying to call function when error (404) appears when loading image.

export default class HotelCards extends React.Component {
  // constructor
  constructor(props){
    super(props)
    this.handleError = this.handleError.bind(this);
  }
  // state
  state = {}

This is the function I'd like to call: (not that if I log this inside render function I get instance of current class)

  handleError() {
    console.log(this);
  }

  render() {
    if (!this.props.hotels) return null;
    return (
        <Grid doubling stackable columns="4" className="cards-container">
        {
            this.props.hotels.map(function(e, i) {
                return (
                  <Grid.Column key={i} className="card-column">
                    <Card>

From this element:

                      <Image src={e.hotel.image} onError={this.handleError} />
                    </Card>
                  </Grid.Column>
                )
            })
        }
      </Grid>
    );
  }//render
}//class

However I get error that this is undefined.

TypeError: this is undefined
Stack trace:
render/<@http://localhost:1337/app/bundle.js:63883:92
...

In vanilla JavaScript my approach for this would be

<img src="image.png" onError="this.onerror=null;this.src='/placeholder.jpg';" />

How do I bind this function to ponent properly?

I have this code. I imported some ponents from Semantic UI.

import React from 'react'
import { Card, Image, Grid } from 'semantic-ui-react'

I am trying to call function when error (404) appears when loading image.

export default class HotelCards extends React.Component {
  // constructor
  constructor(props){
    super(props)
    this.handleError = this.handleError.bind(this);
  }
  // state
  state = {}

This is the function I'd like to call: (not that if I log this inside render function I get instance of current class)

  handleError() {
    console.log(this);
  }

  render() {
    if (!this.props.hotels) return null;
    return (
        <Grid doubling stackable columns="4" className="cards-container">
        {
            this.props.hotels.map(function(e, i) {
                return (
                  <Grid.Column key={i} className="card-column">
                    <Card>

From this element:

                      <Image src={e.hotel.image} onError={this.handleError} />
                    </Card>
                  </Grid.Column>
                )
            })
        }
      </Grid>
    );
  }//render
}//class

However I get error that this is undefined.

TypeError: this is undefined
Stack trace:
render/<@http://localhost:1337/app/bundle.js:63883:92
...

In vanilla JavaScript my approach for this would be

<img src="image.png" onError="this.onerror=null;this.src='/placeholder.jpg';" />

How do I bind this function to ponent properly?

Share Improve this question edited Dec 27, 2016 at 11:14 Kunok asked Dec 27, 2016 at 11:06 KunokKunok 8,8099 gold badges52 silver badges93 bronze badges 1
  • 1 I've just noticed that you're not passing arrow function to map, so the current value of this is lost! – Tomasz Lenarcik Commented Dec 27, 2016 at 11:21
Add a ment  | 

5 Answers 5

Reset to default 3

The typical approach is using the so called "late binding", i.e.

constructor() {
    // ...
    this.handleError = this.handleError.bind(this);
}

handleError() {
    console.log('THIS', this);
}

The reason your code did not work was because your fat arrow is binding to the context in which your class is being defined.

Alternatively, you could also bind at the rendering level as suggested in another answer, so:

<Image src={e.hotel.image} onError={this.handleError.bind(this)} />

However, the problem with that solution is that it produces a new handler function on every call to your render method, which can (but don't have to) negatively influence your rendering performance if you're using some kind of property equality testing optimization techniques.

Ok guys, I found the reason why this is undefined.

It is because these stuff happen inside .map method, so I had to bind this to it like this:

this.props.hotels.map(function(e, i) {
 ...
}, this)

or as @apendua mented, by using arrow function so this doesn't get lost:

 this.props.hotels.map((e, i) => {
     ...
  })

Fat arrow functions as methods in a class are not supported in ES6, so you'd first have to define handError as method like this:

handleError() {
    console.log('test');
}

and you should be able to bind to it so it can use this if required:

 <Image src={e.hotel.image} onError={this.handleError.bind(this} />

To void the bind in your render function (which in some case can have performance) you can do the binding in your constructor function:

this.handleError = this.handleError.bind(this);

@kunok : nice you found your answer. Arrow function ( => ) keep the this context same as enclosing function.

Add this.state is inside ponent the constructor.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744441588a4574385.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信