When I try to set the state in touchablehighlight onpress my app crashes. This is what I got:
<TouchableHighlight onPress={this.setState({toggleCharacter: false})}>
<Image style={styles.tekstballon} source={tekstballon} />
</TouchableHighlight>
My ultimate goal is to toggle toggleCharacter so if it is false I want to set it to true and if it's true I want to set it to false but I am not sure how to.
You're invoking that setState call immediately on render. You need to wrap it in a function that will be called on onPress instead, ie:
<TouchableHighlight onPress={() => this.setState({toggleCharacter: false})}>
Keep in mind, the above is a bit frowned upon as it's creating a new function for every instance but it's just meant to give you an idea of why you're getting your error (a bit more performant to add it to the class itself.)
Edited to answer comment. The 'better' way of doing it mentioned above would be:
class myComponent extends React.Component {
/*
...ctor and methods above
The below assumes Property initializer syntax is available.
If not, you need to autobind in the constructor
/*
handleOnPress = () => this.setState({ toggleCharacter: false })
render() {
return (
<TouchableHighlight onPress={this.handleOnPress}>
<Image style={styles.tekstballon} source={tekstballon} />
</TouchableHighlight>
);
}
}
Related
code:
export default class app extends Component {
state={
name:''
}
render(){
return(
<View>
<TextInput onChangeText={this.handle}></TextInput>
<TouchableOpacity
onPress={this.handleSubmit(this.state.name)}>
<Text>go</Text>
</TouchableOpacity>
</View>
)
}
handle=(text)=>{
this.setState({name:text})
}
handleSubmit=(name)=>{
alert(name)
}
}
every time I enter text,The handleSubmit function will use,why?
<TouchableOpacity
onPress={()=>this.handleSubmit(this.state.name)}>
<Text>go</Text>
</TouchableOpacity>
If i write like this,The problem is solved,but why?
The handleSubmit function invoked automatically every time when the render cycle occurs the component so when the text changes occur and that's why the function automatically invokes so you have to put the arrow function to must call when they go button press event occurs.
as you are using () here in the this.handleSubmit(this.state.name).
So, I recently started making FlatList a recurring thing in the app I'm working on. I am right now working on a screen that gives a list of requests and is updated once one is accepted, which is done by pressing a button. There's a method called getNewRequests I am using to update the requests, but it can't seem to be called by the flatline, as it only returns the error TypeError: _this3 is undefined.
I really need that method to work, because I need to update the state of that screen, and trying to type the whole method there only returns the same error. In that context, this always returns undefined.
render(){
return(
<View style={GenericStyles.styles.genericContainer}>
<Text> REQUEST SCREEN </Text>
<FlatList
data={this.state.requestList}
renderItem={this.renderItem}
keyExtractor={item => item.id}
/>
<Button title="Voltar" color="cyan" onPress={() => this.props.navigation.goBack()}/>
</View>
);
}
renderItem({item}){
return(
<Card
containerStyle={{flex: 1, width: 200}}
title={item.Username}>
<Button color="blue" title="Accept" onPress={() => RequestService.allowRequest(item.id, (response) => {
let rsp = JSON.parse(response);
if(rsp.success){
this.getNewRequests();
}
})}/>
</Card>
);
}
You need to either bind the function in your constructor (or wherever you want) doing:
constructor(props){
super(props)
this.renderItem.bind(this)
}
or use arrow function:
renderItem = ({item}) => {
//your function
}
Doing this will give the function access to the this of the current component.
The idea is to create a specific Touchable component acting like a button and have a feeling of pressed and unpressed, and using this component many times on my app but only one can be pressed at a time. If one is touched and then another one is touched, the first one should be unpressed and the second one should be pressed. The idea is not to use Redux to solve this problem.
I'm already handling which component was pressed, and sending through props the actions to the component. But i don't know how to manage all buttons at the same time in a generic way, by that I mean, not creating a variable to each button.
my App:
<View>
<ActivityButton activityTitle={"B1"} submit={() => this.submitHandler("B1")} />
<ActivityButton activityTitle={"B2"} submit={() => this.submitHandler("B2")} />
</View>
my Component (ActivityButton):
this.state={active:false}
<TouchableOpacity style={this.state.active ? styles.buttonPress : styles.button} onPress={this.props.submit}>
<View>
<Text>{this.props.activityTitle}</Text>
</View>
</TouchableOpacity>
I assume what you trying to do something like a Radio button groups? If your buttons only located in single page, you can achieve by using state in MyApp to check which buttons is enabled instead of button itself.
MyApp
constructor(props) {
super(props);
this.state = {
buttonIdThatEnable: "",
};
}
submitHandler = (buttonId) => {
this.setState({
buttonIdThatEnable: buttonId,
});
}
render() {
return (
<View>
<ActivityButton
activityTitle={"B1"}
active={this.state.buttonIdThatEnable === "B1"}
submit={() => this.submitHandler("B1")}
/>
<ActivityButton
activityTitle={"B2"}
active={this.state.buttonIdThatEnable === "B2"}
submit={() => this.submitHandler("B2")}
/>
</View>
)
}
ActivityButton (Use props.active to determine style)
<TouchableOpacity style={this.props.active ? styles.buttonPress : styles.button}
onPress={this.props.submit}>
<View>
<Text>{this.props.activityTitle}</Text>
</View>
</TouchableOpacity>
If your Buttons are located in different components and you do not want to use Redux, you may consider the React Context API
The question is almost similar to this one :
touchableopacity onpress function undefined (is not a function) React Native
But the problem is, I am getting the error despite the fact that I have bind the function. Here is my TouchableOpacity component:
<TouchableOpacity style={styles.eachChannelViewStyle} onPress={() => this.setModalVisible(true)}>
{item.item.thumbnail ?
<Image style={styles.everyVideoChannelThumbnailStyle} source={{uri: item.item.thumbnail}} />
: <ActivityIndicator style= {styles.loadingButton} size="large" color="#0000ff" />}
<Text numberOfLines={2} style={styles.everyVideoChannelVideoNameStyle}>
{item.item.title}
</Text>
</TouchableOpacity>
And this is my setModalVisible function:
setModalVisible(visible) {
console.error(" I am in set modal section ")
this.setState({youtubeModalVisible: visible});
}
Also, I have bind the function in constructor as follows:
this.setModalVisible = this.setModalVisible.bind(this);
But, I am still getting same error that undefined is not a function. Any help regarding this error?
The render method and your custom method must be under the same scope. In code below I have demonstrated the same. I hope you will modify your code accordingly as I assume you got the gist :)
class Demo extends Component {
onButtonPress() {
console.log("click");
}
render() {
return (
<View>
<TouchableOpacity onPress={this.onButtonPress.bind(this)}>
<Text> Click Me </Text>
</TouchableOpacity >
<View>
);
}
}
Alternatively binding method in constructor will also work
class Demo extends Component {
constructor(props){
super(props);
this.onButtonPress= this.onButtonPress.bind(this);
}
onButtonPress() {
console.log("click");
}
render() {
return (
<View>
<TouchableOpacity onPress={this.onButtonPress()}>
<Text> Click Me </Text>
</TouchableOpacity >
<View>
);
}
}
I'm not sure if this will help but I write my functions this way and haven't encountered this problem.
If I were you I'd try binding the function in the place where you declare it.
setModalVisible = (visible) => {
this.setState({ youtubeModalVisible: visible });
}
If you do this, you don't have to bind in the constructor.
constructor(props) {
...
// Comment this out to see it will still bind.
// this.setModalVisible = this.setModalVisible.bind(this);
...
}
Lastly, if this function will only set the modal's state to visible, you might want to remove the argument and pass it this way.
<TouchableOpacity style={styles.eachChannelViewStyle} onPress={this.setModalVisible}>
...
</TouchableOpacity>
// Refactored function declaration would look like this
setModalVisible = () => {
this.setState({ youtubeModalVisible: true });
}
I implemented a sign in page that worked up until I upgraded react-native.
The problem I'm having is that the onPress prop isn't being called:
<TouchableHighlight style={styles.button}
underlayColor='#f1c40f'
onPress={this.signIn}>
<Text style={styles.buttonText}>Sign In</Text>
</TouchableHighlight>
Here is my signIn function:
signIn: function(){
console.log("SignInAction signIn")
this.fetchData(); },
The signIn button appears to be depressed when I click it but the log statement isn't firing.
Try calling it like this:
onPress={ () => this.signIn() }>
It looks like the "this" in your function is bound to the wrong scope.
you can also do it like this:
onPress={this.signIn.bind(this)}>
the rest of code don't need change.
Also, if you don't wanna use bind and since we're using ES6 syntax, you could write your function out assigned as a const and arrow-function (within your component) rather than a function eg:
signIn = () => {
// code here
}
then you can still call it within the component like you already are without having to bind within the constructor or anywhere else:
<TouchableHighlight style={styles.button}
underlayColor='#f1c40f'
onPress={this.signIn}>
<Text style={styles.buttonText}>Sign In</Text>
</TouchableHighlight>
This should keep context of "this" consistent since signIn will be bound to the component only once on initialization.