I have this code. I imported some components 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 component properly?
The typical approach is using the so called "late binding", ie
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.
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);
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 commented, by using arrow function so this
doesn't get lost:
this.props.hotels.map((e, i) => {
...
})
@kunok : nice you found your answer. Arrow function ( => ) keep the this context same as enclosing function.
添加this.state是组件内部的构造函数。
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.