[英]How to access `this` inside a renderRow of a ListView?
I'm having trouble to run a function for the onPress event inside a row of a ListView
. 我在ListView
的一行内为onPress事件运行函数时遇到麻烦。 I'm following the React Native tutorial trying to continue from there. 我正在关注React Native教程,试图从那里继续。 It seems it's using ES6 syntax style. 似乎它使用的是ES6语法样式。
This is the relevant part of the code. 这是代码的相关部分。
/**
* Sample React Native App
* https://github.com/facebook/react-native
*/
import React, {
TouchableHighlight,
AppRegistry,
Component,
Image,
ListView,
StyleSheet,
Text,
View,
Alert,
} from 'react-native';
class AwesomeProject extends Component {
constructor(props) {
super(props);
this.something = this.something.bind(this); // <-- Trying this, not even sure why
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
loaded: false,
};
}
//
//Irrelevant code here. Fetching stuff and renderLoadingView
//
something = function(){
console.log('something');
Alert.alert(
'Alert Title',
'alertMessage',
);
}
render() {
console.log('this', this); //this is an instance of AwesomeProject
if (!this.state.loaded) {
return this.renderLoadingView();
}
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderMovie}
style={styles.listView}
/>
);
}
renderMovie(movie) {
console.log('Not this', this); //this is not an instance of AwesomeProject
return (
<TouchableHighlight onPress={() => {console.log(this); this.something()}}>
<View style={styles.container}>
<Image
source={{uri: movie.posters.thumbnail}}
style={styles.thumbnail}
/>
<View style={styles.rightContainer}>
<Text style={styles.title}
>{movie.title}</Text>
<Text style={styles.year}>{movie.year}</Text>
</View>
</View>
</TouchableHighlight>
);
}
}
//
//More irrelevant code here. Styles and the
//
AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);
I'm unable to run the something
function. 我无法运行something
函数。 I've tried various syntax without success. 我尝试了各种语法,但没有成功。 The problem seems to be that this
is not what I expect it to be, and it doesn't have the variable something
defined. 这个问题似乎是, this
不是我希望它是,并且它不具有可变something
定义。
The only way I had to make it work was to declare an external variable with var something = function(){...}
outside the AwesomeProject class. 我必须使其起作用的唯一方法是在AwesomeProject类外部使用var something = function(){...}
声明一个外部变量。
Is there a way to access something
while being declared inside AwesomeProject
? 在AwesomeProject
中声明时,是否可以访问something
AwesomeProject
? Is this maybe a bad practice according to flux architecture or something? 根据磁通架构,这可能是不好的做法吗?
Turns out I found the solution myself, here: https://github.com/goatslacker/alt/issues/283#issuecomment-115391700 原来我自己在这里找到了解决方案: https : //github.com/goatslacker/alt/issues/283#issuecomment-115391700
The problem is that with ES6 syntax you have no autobinding of
this
, so you need to do it yourself.
问题是,与ES6语法,你有没有自动绑定
this
,所以你需要自己做。
I've learned a bit more since I posted this answer. 自发布此答案以来,我学到了更多。 The real problem is that
this
is "bound" when the function is executed, not when it's declared. 真正的问题是在执行函数时(而不是在声明时)this
是“绑定”的。 It points to the object the function is attached to when called . 它指向函数在调用时附加的对象。 For example: 例如:obj.foo(); //inside foo, this points to obj bar(); //inside bar, this points to the global object (or undefined in strict mode)
In my example the function
this.renderMovie()
is passed as a parameter. 在我的示例中,函数this.renderMovie()
作为参数传递。 So inside ListView it will be a "local variable". 因此,在ListView中它将是一个“局部变量”。 It will be called "detached" from any object, like thebar()
example before, sothis
will not be what I expect. 它将被称为与任何对象“分离”,例如之前的bar()
示例,因此this
不是我期望的。It's possible to force the binding of
this
. 可以强制this
绑定。
There are 3 possible solutions to my problem, and I like the 3rd one the best: 有3种可能的解决方案,我最喜欢第3种:
On the code, replace the referece to {this.renderMovie}
whith {this.renderMovie.bind(this)}
在代码上,将{this.renderMovie}
替换为{this.renderMovie.bind(this)}
render() {
console.log('this', this); //this is an instance of AwesomeProject
if (!this.state.loaded) {
return this.renderLoadingView();
}
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderMovie.bind(this)} //<-- change here
style={styles.listView}
/>
);
}
And of course, bind the right function: 当然,绑定正确的函数:
constructor(props) {
super(props);
this.something = this.something.bind(this); // <-- Not this function
this.renderMovie = this.renderMovie.bind(this); // <-- This function!!
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
loaded: false,
};
}
I like this one the best. 我最喜欢这个。 You just need to declare the involved function using the arrow syntax so this: 您只需要使用箭头语法声明所涉及的函数,因此:
renderMovie(movie) {
//code here
}
becomes this: 变成这个:
renderMovie = (movie) => {
//code here
}
In addition to https://stackoverflow.com/a/36779517/6100821 除了https://stackoverflow.com/a/36779517/6100821
<ListView
dataSource={this.state.dataSource}
renderRow={::this.renderMovie} //<-- cleaner, than bind
style={styles.listView}
/>
Be careful, it's just a proposal , not a standard! 注意,这只是一个建议 ,而不是标准!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.