最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin5浏览0评论

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.

发布评论

评论列表(0)

  1. 暂无评论