我如何在React天然中的范围之外绑定一个函数?我会遇到错误:
undefined is not an object evaluating this.state
&
undefined is not an object evaluating this.props
加载数据后,我正在使用渲染方法唤起renderGPSDataFromServer()
。问题是,我正在尝试在renderGPSDataFromServer()
内使用_buttonPress()
和calcRow()
,但是我会遇到这些错误。
我添加了
constructor(props) {
super(props);
this._buttonPress = this._buttonPress.bind(this);
this.calcRow = this.calcRow.bind(this);
转到我的构造函数,我将_buttonPress() {
更改为_buttonPress = () => {
,但仍然没有。
我认为我理解这个问题,但我不知道如何解决:
renderLoadingView() {
return (
<View style={[styles.cardContainer, styles.loading]}>
<Text style={styles.restData}>
Loading ...
</Text>
</View>
)
}
_buttonPress = () => {
this.props.navigator.push({
id: 'Main'
})
}
renderGPSDataFromServer =() => {
const {loaded} = this.state;
const {state} = this.state;
return this.state.dataArr.map(function(data, i){
return(
<View style={[styles.cardContainer, styles.modularBorder, styles.basePadding]} key={i}>
<View style={styles.cardContentLeft}>
<TouchableHighlight style={styles.button}
onPress={this._buttonPress().bind(this)}>
<Text style={styles.restData}>View Video</Text>
</TouchableHighlight>
</View>
<View style={styles.cardContentRight}>
<Text style={styles.restData}>{i}</Text>
<View style={styles.gpsDataContainer}>
<Text style={styles.gpsData}>
{Number(data.lat).toFixed(2)}</Text>
<Text style={styles.gpsData}>{Number(data.long).toFixed(2)}</Text>
</View>
<Text style={styles.gpsData}>
{this.calcRow(55,55).bind(this)}
</Text>
</View>
</View>
);
});
}
render = ()=> {
if (!this.state.loaded) {
return this.renderLoadingView();
}
return(
<View>
{this.renderGPSDataFromServer()}
</View>
)
}};
我该如何解决此问题,在这种情况下,问题是什么?
this.props是只读的
react docs-组件和props
因此,组件不应尝试修改它们,更不用说在这里进行突变:
_buttonPress = () => {
this.props.navigator.push({
id: 'Main'
})
}
我建议使用状态:
_buttonPress = () => {
this.setState = {
...this.state,
navigator: {
...this.state.navigator,
id: 'Main'
}
}
}
关于您的约束性问题:
.map
方法采用第二个参数,用于在调用回调时设置this
的值。
在问题的上下文中,您只需要将this
作为第二个参数将其传递给您的.map
方法即可将组件范围的this
绑定到它。
这正在发生,因为map
方法中的功能会创建不同的上下文。您可以将箭头函数用作词汇绑定的map
方法中的回调。这应该解决您存在的问题。
renderGPSDataFromServer =() => {
const {loaded} = this.state;
const {state} = this.state;
return this.state.dataArr.map((data, i) => {
return(
<View style={[styles.cardContainer, styles.modularBorder, styles.basePadding]} key={i}>
<View style={styles.cardContentLeft}>
<TouchableHighlight style={styles.button}
onPress={this._buttonPress().bind(this)}>
<Text style={styles.restData}>View Video</Text>
</TouchableHighlight>
</View>
<View style={styles.cardContentRight}>
<Text style={styles.restData}>{i}</Text>
<View style={styles.gpsDataContainer}>
<Text style={styles.gpsData}>
{Number(data.lat).toFixed(2)}</Text>
<Text style={styles.gpsData}>{Number(data.long).toFixed(2)}</Text>
</View>
<Text style={styles.gpsData}>
{this.calcRow(55,55).bind(this)}
</Text>
</View>
</View>
);
});
}
另外,一旦您在类函数定义中使用了箭头函数,您 不需要在构造函数中绑定它们:
constructor(props) {
super(props);
this._customMethodDefinedUsingFatArrow = this._customMethodDefinedUsingFatArrow.bind(this)
}
另外,一旦将类函数定义为箭头功能,您就可以 调用它们时,不需要使用箭头功能:
class Example extends React.Component {
myfunc = () => {
this.nextFunc()
}
nextFunc = () => {
console.log('hello hello')
}
render() {
// this will give you the desired result
return (
<TouchableOpacity onPress={this.myFunc} />
)
// you don't need to do this
return (
<TouchableOpacity onPress={() => this.myFunc()} />
)
}
}
不确定这是否是问题,但我认为代码是错误的,并且可能导致您的问题。
<View style={styles.cardContentLeft}>
<TouchableHighlight style={styles.button}
onPress={this._buttonPress().bind(this)}>
<Text style={styles.restData}>View Video</Text>
</TouchableHighlight>
</View>
特别是该行onPress={this._buttonPress().bind(this)}>
您正在调用该功能并同时绑定它。
正确的方法将是如此
onPress={this._buttonPress.bind(this)}>
这样,该函数将仅称为OnPress。
您要朝着正确的方向前进,但是仍然存在一个小问题。您将function
传递给map
回调,该回调的范围(this
)与组件不同(因为它不是箭头函数),因此,当您执行bind(this)
时,您正在重新使用回调来使用map
的范围。我认为这应该有效,它基本上将您传递给map
的回调变成了箭头功能。另外,由于您在构造函数中bind
您的功能,因此您无需再做一次:
// The constructor logic remains the same
// ....
renderLoadingView() {
return (
<View style={[styles.cardContainer, styles.loading]}>
<Text style={styles.restData}>
Loading ...
</Text>
</View>
)
}
_buttonPress = () => {
this.props.navigator.push({
id: 'Main'
})
}
renderGPSDataFromServer =() => {
const {loaded} = this.state;
const {state} = this.state;
return this.state.dataArr.map((data, i) => {
return(
<View style={[styles.cardContainer, styles.modularBorder, styles.basePadding]} key={i}>
<View style={styles.cardContentLeft}>
<TouchableHighlight style={styles.button}
onPress={this._buttonPress}>
<Text style={styles.restData}>View Video</Text>
</TouchableHighlight>
</View>
<View style={styles.cardContentRight}>
<Text style={styles.restData}>{i}</Text>
<View style={styles.gpsDataContainer}>
<Text style={styles.gpsData}>
{Number(data.lat).toFixed(2)}</Text>
<Text style={styles.gpsData}>{Number(data.long).toFixed(2)}</Text>
</View>
<Text style={styles.gpsData}>
{this.calcRow(55,55).bind(this)}
</Text>
</View>
</View>
);
});
}
render = ()=> {
if (!this.state.loaded) {
return this.renderLoadingView();
}
return(
<View>
{this.renderGPSDataFromServer()}
</View>
)
}};