s2t2 s2t2 - 1 month ago 10
Javascript Question

React Native ES6 `extends Component` - How to invoke a component function and pass params?

The

handleButtonPress
function works in the following example when no params are required...



import React, { Component } from 'react';
import {View, Text, TouchableOpacity} from 'react-native';

export default class MyComponent extends Component {
constructor(props){
super(props)
this.state = {message:"HELLO"}
this.myFunc = this.myFunc.bind(this)
this.handleButtonPress = this.handleButtonPress.bind(this)
}

render(){
return (
<View>
<Text>{this.state.message}</Text>
<TouchableOpacity onPress={this.handleButtonPress}>
<Text>Press Me</Text>
</TouchableOpacity>
</View>
)
}

handleButtonPress(){
console.log("BUTTON WAS PRESSED")
this.myFunc()
}

myFunc(){
console.log("MY FUNCTION WAS CALLED")
this.setState({message:"GOODBYE"})
}

}





... but doesn't work in the following example when params are required:



render(){
return (
<View>
<Text>{this.state.message}</Text>
<TouchableOpacity onPress={function(){ this.handleButtonPress("GOODBYE") }}>
<Text>Press Me</Text>
</TouchableOpacity>
</View>
)
}

handleButtonPress(message){
console.log("BUTTON WAS PRESSED WITH MESSAGE: " + message)
this.myFunc(message)
}

myFunc(message){
console.log("MY FUNCTION WAS CALLED")
this.setState({message:message})
}





It throws:
undefined is not a function (evaluating 'this.handleButtonPress("GOODBYE")')


One strategy I've been using is to reference the
handleButtonPress
function again inside the
render
function, like this:



render(){
handlePress = this.handleButtonPress;

return (
<View>
<Text>{this.state.message}</Text>
<TouchableOpacity onPress={function(){ handlePress("GOODBYE") }}>
<Text>Press Me</Text>
</TouchableOpacity>
</View>
)
}





... but is there another/better way?

Answer

Since there's an anonymous function, the this context inside is the global window object. Since there is no handleButtonPress present, it throws the error. Your workaround works because this still refers to the class outside the anonymous function, thus allowing you to assign it's reference to handlePress and call it.

To combat this, you can use Function.prototype.bind which will supplement a this context to the function. From the documentation linked:

The bind() method creates a new function that, when called, has its this keyword set to the provided value...

You can apply it here like so:

<TouchableOpacity onPress={function() { this.handleButtonPress("GOODBYE") }.bind(this)}>

This will set the this context of the anonymous function to the class, instead of the global window object, thus allowing you to call this.handleButtonPress.