[英]How to access `this` inside a renderRow of a ListView?
我在ListView
的一行內為onPress事件運行函數時遇到麻煩。 我正在關注React Native教程,試圖從那里繼續。 似乎它使用的是ES6語法樣式。
這是代碼的相關部分。
/**
* 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);
我無法運行something
函數。 我嘗試了各種語法,但沒有成功。 這個問題似乎是, this
不是我希望它是,並且它不具有可變something
定義。
我必須使其起作用的唯一方法是在AwesomeProject類外部使用var something = function(){...}
聲明一個外部變量。
在AwesomeProject
中聲明時,是否可以訪問something
AwesomeProject
? 根據磁通架構,這可能是不好的做法嗎?
原來我自己在這里找到了解決方案: https : //github.com/goatslacker/alt/issues/283#issuecomment-115391700
問題是,與ES6語法,你有沒有自動綁定
this
,所以你需要自己做。
自發布此答案以來,我學到了更多。 真正的問題是在執行函數時(而不是在聲明時)
this
是“綁定”的。 它指向函數在調用時附加的對象。 例如:obj.foo(); //inside foo, this points to obj bar(); //inside bar, this points to the global object (or undefined in strict mode)
在我的示例中,函數
this.renderMovie()
作為參數傳遞。 因此,在ListView中它將是一個“局部變量”。 它將被稱為與任何對象“分離”,例如之前的bar()
示例,因此this
不是我期望的。可以強制
this
綁定。
有3種可能的解決方案,我最喜歡第3種:
在代碼上,將{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}
/>
);
}
當然,綁定正確的函數:
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,
};
}
我最喜歡這個。 您只需要使用箭頭語法聲明所涉及的函數,因此:
renderMovie(movie) {
//code here
}
變成這個:
renderMovie = (movie) => {
//code here
}
除了https://stackoverflow.com/a/36779517/6100821
<ListView
dataSource={this.state.dataSource}
renderRow={::this.renderMovie} //<-- cleaner, than bind
style={styles.listView}
/>
注意,這只是一個建議 ,而不是標准!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.