Why is my React Native TouchableOpacity onPress function not functioning properly?

Embarking on my journey with React Native (or any JS framework for that matter), I decided to delve into creating a simple tap game. The concept is straightforward: tap on the blue square, watch it randomly relocate, and repeat the process. Here is a snippet of the code I've crafted thus 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>
        );
    }
}

Despite a lengthy chunk of code present, I felt it necessary to provide full context. Moving along, the current roadblock lies within my renderFirstStage() function. Upon closer inspection, notice where an onPress event handler is utilized to call upon the function this.score? When running the program and tapping on those TouchableOpacities, an error surfaces: _this5.score is not a function... _this5.score is undefined. Upon brainstorming, it appears that when calling onPress={()=>this.score} from JavaScript embedded in JSX, accessing methods within the App class poses a challenge. I suspect an issue with the scope, though without certainty. How might one execute the score method inside my TouchableOpacity components successfully? Every attempt I've made yields no positive outcome...

Please note: My setup involves an iPhone 7 emulator on a MacBook Pro.

Answer №1

Indeed, there is a scope issue that needs to be addressed. To resolve this, it's necessary to ensure the function is properly bound to the correct this context within the constructor.

constructor(props) {
    super();
    this.state = {
        showStartButton: true, // make sure to revert back to true
        score: 0
    }
    this.renderFirstStage = this.renderFirstStage.bind(this);
}

Alternatively, you can opt to use call to immediately invoke the function and bind it accordingly with this.

{!this.state.showStartButton ? this.renderFirstStage.call(this) : null}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Automatically compile files while performing an npm install or update

I am looking for a way to automatically compile my TypeScript code into JavaScript when another project requires it. For example, when a project runs npm install or updates with my project as a dependency, I want a specific command to be executed after all ...

Tips for accessing form data that has been automatically uploaded in PHP

I've been trying to automatically post data using JavaScript and retrieve it in a PHP file. However, I am facing an issue where the PHP file is not able to retrieve the data. I have set up an automatic form that takes input from another form and send ...

The absence of a type annotation for `T` has been noted

Attempting to create code with a simple JavaScript function: filterArray(user: any, items: Array<Object>) { items = items.filter(item => {return true;}); return items; } Encountering the following error: Error message: Missing type anno ...

What are the advantages of utilizing NGRX over constructor-injected services?

Have you ever wondered about the benefits of using NGRX or NGXS for an Angular application instead of constructor injected services to manage component IO? Is it simply to prevent mutation of component properties references without replacing the entire pr ...

Replicate a click using jQuery to retrieve a filtered multigallery based on the URL

I have a website that was built using Elementor for a photographer. The site features an Elementor Multigallery with a filter at the top. I am looking to create external links that will direct users to specific subpages showing only filtered items. For ex ...

If other options fail, Else If may not be a suitable choice

This is the process: switching from Issue: x==0||1 to x==0||x==1 etc. This code runs from an .html file <body> <div class="" id="pimg1"> </body><script> var x=new Date().getMonth(); if (x == 0||x == 5||x == 2){docu ...

NodeJS domain error handling failing to catch ReferenceError exceptions

I'm currently facing some challenges with domains in NodeJS. I've set up middleware functions to wrap every call in my web application within a domain in order to capture errors, process them, and return informative error messages. While this se ...

Dynamic horizontal scrolling

I need help implementing a site using React that scrolls horizontally. I'm unsure how to implement certain aspects, so I am looking for some assistance. Within a wrapper, I have multiple container Divs. <div class="wrapper"> <div class=" ...

Tips for transferring an image array by index from OneViewController to AnotherViewController on iOS?

As a newcomer to iOS Development, I recently created an application that utilizes JSON data. I successfully parsed this data into an array, which also contains another nested array. This nested array is also accessed by index in my code: if (responsedata. ...

Prevent the Rain from descending

Looking for a way to toggle a particle emitter on or off, I've encountered memory leaks with my Reactjs code that generates rain/snow particles using the canvas element. Despite attempts to stop the animation properly, it seems to be projecting a new ...

Does the downloading of images get affected when the CSS file has the disabled attribute?

Is it possible to delay the download of images on a website by setting the stylesheet to 'disabled'? For example: <link id="imagesCSS" rel="stylesheet" type="text/css" href="images.css" disabled> My idea is to enable the link later to tri ...

How can I efficiently retrieve the "value" of a cookie and store it in a .txt file using Python?

Seeking to automate certain requests, I am currently using selenium's get_cookie function to extract cookies from a website. The retrieved cookie data is returned as a dict structured like this: {'domain': 'website-name-here', &a ...

Combining inheritance and isolated scopes: a comprehensive guide

I've encountered a situation where I need to sort an HTML table. Here is the code snippet: <table> <thead> <tr> <th custom-sort-one order="'Name'" >Name</th> </ ...

Is XMLHttpRequest just sitting idle...?

As a newcomer to the world of javascript and AJAX, I've been stuck on a single problem for the past 8 hours. Despite my best efforts, I just can't seem to figure out what's going wrong. On my website, I have an image with an onclick event ca ...

The issue with the $(window).width() property not functioning correctly in Internet Explorer

Currently, I have a Div element with absolute positioning: <div id="target" style="height: 300px; position: absolute; top: 275px;"></div> My goal is to calculate the horizontal resolution of the screen using JavaScript. With this width, I the ...

The Cloudinary setup does not retrieve information from the .env file

I am currently integrating Cloudinary with my node.js project... Unfortunately, I have encountered an issue where cloudinary.config is not able to read data from the .env file. Instead, I am required to input them directly into the code! const cloudinary ...

Launch all external links in Browser (NWjs)

While attempting to create my own independent version of Google Chat using NWjs, I encountered some obstacles. When a link is opened in the NWjs window, it opens in another NWjs window instead of the default system browser, which is what I want. I attemp ...

Need to double tap to remove item in redux-toolkit

Trying to delete an item in Redux Toolkit, but having trouble as the remove function only works on screen. I have to press twice to delete the previous one. Here is the reducer: const noteReducer = createSlice({ name: "note", initialState: N ...

Creating a new web application, I require a loading overlay to appear during transitions between pages

I've checked high and low, but I can't seem to find the solution! My webapp has a page that is bogged down with data causing it to load slowly. Is there a way to display a loading div while transitioning to the next page? Perhaps something like ...

Leveraging angular.extend() with controllers and function overrides

Currently, I am working with Angular 1.4.8 and attempting to expand a controller. The original controller and the expanding controller are quite similar, but there is a specific function that I aim to replace in the extending controller. angular.module(&a ...