[英]Undefined is not an object evaluating this.state/this.props
How do I bind a function outside of scope in React Native? 如何在React Native中将函数绑定到范围之外? I'm getting the errors:
我遇到了错误:
undefined is not an object evaluating this.state
& &
undefined is not an object evaluating this.props
I'm using the render method to evoke renderGPSDataFromServer()
when the data has been loaded. 加载数据后,我正在使用render方法来调用
renderGPSDataFromServer()
。 The problem is, I'm trying to use _buttonPress()
and calcRow()
inside of renderGPSDataFromServer()
, but I'm getting those errors. 问题是,我试图在
calcRow()
内使用_buttonPress()
和renderGPSDataFromServer()
,但是却遇到了这些错误。
I've added 我已经添加
constructor(props) {
super(props);
this._buttonPress = this._buttonPress.bind(this);
this.calcRow = this.calcRow.bind(this);
to my constructor and I've changed _buttonPress() {
to _buttonPress = () => {
and still nothing. 到我的构造函数,并且我已经将
_buttonPress() {
更改为_buttonPress = () => {
仍然没有。
I think I understand the problem but I don't know how to fix it: 我认为我了解问题,但不知道如何解决:
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>
)
}};
How do I go about fixing this and in this case what is the problem? 我该如何解决这个问题,在这种情况下是什么问题?
this.props are read-only
this.props是只读的
React docs - component and props React文档-组件和道具
And therefore a component shouldn't try a to modify them let alone mutate them as you are doing here: 因此,组件不应尝试对其进行修改,更不用说像在这里所做的那样对其进行变异了:
_buttonPress = () => {
this.props.navigator.push({
id: 'Main'
})
}
I'd suggest using state instead: 我建议改为使用状态:
_buttonPress = () => {
this.setState = {
...this.state,
navigator: {
...this.state.navigator,
id: 'Main'
}
}
}
Regarding your binding issue: 关于您的约束问题:
the .map
method takes a 2nd argument that is used to set the value of this
when the callback is invoked. 该
.map
方法采用用于设置的值的第二参数this
被调用的回调时。
In the context of your question, you just need to pass this
as the 2nd argument to you .map
method to bind the components scope's this
to it. 在问题的上下文中,您只需要
this
作为第二个参数传递给.map
方法即可将组件范围的this
绑定到它。
This is happening because, the function inside the map
method creates a different context. 发生这种情况是因为
map
方法内部的函数创建了不同的上下文。 You can use arrow functions as the callback in the map
method for lexical binding. 您可以在
map
方法的词法绑定中使用箭头函数作为回调。 That should solve the issue you are having. 那应该可以解决您遇到的问题。
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> ); }); }
Also, once you've used arrow functions in the class function definition you don't need to bind them in constructor like:
同样,一旦在类函数定义中使用了箭头函数,就不需要像以下那样在构造函数中绑定它们:
constructor(props) { super(props); this._customMethodDefinedUsingFatArrow = this._customMethodDefinedUsingFatArrow.bind(this) }
Also, once you have defined class functions as arrow functions, you don't need to use the arrow functions while calling them either:
同样,一旦将类函数定义为箭头函数,则在调用它们时不需要使用箭头函数:
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()} /> ) } }
not sure if this is the problem, but I think is code is wrong, and may be potentially causing your issue. 不知道这是否是问题,但我认为代码是错误的,并且可能会导致您的问题。
<View style={styles.cardContentLeft}>
<TouchableHighlight style={styles.button}
onPress={this._buttonPress().bind(this)}>
<Text style={styles.restData}>View Video</Text>
</TouchableHighlight>
</View>
specifically this line onPress={this._buttonPress().bind(this)}>
you are invoking the function and binding it at the same time. 特别是
onPress={this._buttonPress().bind(this)}>
这一行,您在调用该函数并同时绑定它。
The correct way to do this would be so 正确的方法是
onPress={this._buttonPress.bind(this)}>
this way the function will be called only onPress. 这样,该函数将仅在onPress上调用。
You are going in the right direction, but there is still a minor issue. 您的方向是正确的,但仍然存在一个小问题。 You are passing a
function
to your map
callback that has a different scope ( this
) than your component (because it is not an arrow function), so when you do bind(this)
, you are rebinding your callback to use the scope from map
. 您正在将
function
传递给map
回调,该function
作用域( this
)与组件的作用域不同(因为它不是箭头函数),因此当您执行bind(this)
,您将重新绑定回调以使用map
的作用域。 I think this should work, it basically turns the callback that you pass to map
into an arrow function. 我认为这应该起作用,它基本上将传递给
map
的回调转变为箭头函数。 Also, since you bind
your function in the constructor, you do not need to do it again: 另外,由于您
bind
函数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>
)
}};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.