Reputation: 155
I'm new to react native (or any JS framework for that matter), and I'm trying to make a simple tap game where once you tap on the blue square it randomly renders in a different location, then you tap again, and so on. Here's my code so far:
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
TouchableOpacity,
View
} from 'react-native';
import styles from './src/styles/style';
export default class App extends Component<{}> {
constructor(props) {
super();
this.state = {
showStartButton: true, // change back to true
score: 0
}
}
startGame() {
this.setState({
showStartButton: !this.state.showStartButton
});
this.renderFirstStage();
}
score() {
this.setState({
showStartButton: !this.state.showStartButton,
score: score+1
});
}
renderStartButton() {
return (
<TouchableOpacity style={styles.startButton} onPress={()=>this.startGame()}>
<Text style={styles.startButtonText}>START</Text>
</TouchableOpacity>
);
}
renderWhiteBox() {
return (
<View style={{flex: 1, backgroundColor: 'white'}} />
);
}
renderBlueBox() {
return (
<View style={{flex: 1, backgroundColor: 'blue'}} />
);
}
renderFirstStage() {
var blueColNum = Math.floor(Math.random() * 6);
var blueRowNum = Math.floor(Math.random() * 4);
var col1 = ['white', 'white', 'white', 'white', 'white', 'white'];
var col2 = ['white', 'white', 'white', 'white', 'white', 'white'];
var col3 = ['white', 'white', 'white', 'white', 'white', 'white'];
var col4 = ['white', 'white', 'white', 'white', 'white', 'white'];
if (blueRowNum == 0)
col1[blueColNum] = 'blue';
else if (blueRowNum == 1)
col2[blueColNum] = 'blue';
else if (blueRowNum == 2)
col3[blueColNum] = 'blue';
else if (blueRowNum == 3)
col4[blueColNum] = 'blue';
return (
<View style={{flex: 1, flexDirection: 'row'}}>
<View style={{flex: 1}}>
<View style={styles.scoreBoard}><Text style={styles.timerText}>Time: {blueRowNum}</Text></View>
{col1.map(function(el){
if (el == 'blue')
return (
<TouchableOpacity style={{flex: 1, backgroundColor: el}} onPress={()=>this.score()} />
);
else
return (
<View style={{flex: 1, backgroundColor: el}} />
);
})}
</View>
<View style={{flex: 1}}>
<View style={{flex: 1, backgroundColor: 'gray'}} />
{col2.map(function(el){
if (el == 'blue')
return (
<TouchableOpacity style={{flex: 1, backgroundColor: el}} onPress={()=>this.score()}/>
);
else
return (
<View style={{flex: 1, backgroundColor: el}} />
);
})}
</View>
<View style={{flex: 1}}>
<View style={{flex: 1, backgroundColor: 'gray'}} />
{col3.map(function(el){
if (el == 'blue')
return (
<TouchableOpacity style={{flex: 1, backgroundColor: el}} onPress={()=>this.score()} />
);
else
return (
<View style={{flex: 1, backgroundColor: el}} />
);
})}
</View>
<View style={{flex: 1}}>
<View style={styles.scoreBoard}><Text style={styles.timerText}>Score: {this.state.score}</Text></View>
{col4.map(function(el){
if (el == 'blue')
return (
<TouchableOpacity style={{flex: 1, backgroundColor: el}} onPress={()=>this.score()} />
);
else
return (
<View style={{flex: 1, backgroundColor: el}} />
);
})}
</View>
</View>
);
}
render() {
return (
<View style={styles.container}>
{this.state.showStartButton ? this.renderStartButton() : null}
{!this.state.showStartButton ? this.renderFirstStage() : null}
</View>
);
}
}
So that's a lot of code but I figured to include it all for context's sake. Anyways, the issue I'm having is with my renderFirstStage() function. See in the return statement where I'm calling an onPress event handler to run the function this.score? Ok, so when I run the program and I tap on one of those TouchableOpacities I get an error reading: _this5.score is not a function... _this5.score is undefined. My best guess is that since I'm calling the onPress={()=>this.score} from within JS code that is within JSX, and I somehow don't have access to methods in the App class. So I'm thinking something is wrong with the scope, or maybe not, I don't know. Even if my hunch is correct, I have no idea how to correct it. How can I call the score method from inside my TouchableOpacity components? Nothing I've tried seems to work for me...
Note: I'm running on an iPhone 7 emulator on a MacBook pro.
Upvotes: 1
Views: 5729
Reputation: 5135
Yes it has the scope problem, you need to bind
the function
with this
context in your constructor
constructor(props) {
super();
this.state = {
showStartButton: true, // change back to true
score: 0
}
this.renderFirstStage = this.renderFirstStage.bind(this);
}
Or you may simply use call
to invoke the function
immediately and bind it with this
{!this.state.showStartButton ? this.renderFirstStage.call(this) : null}
Upvotes: 1