Button action called without pressing it - react-native

I had a render function with a button that redirects to another page.
When I enter the page, it does immediately trigger to the page (without cliking the button) and display the following warning message : cannot update during an existing state transition
render () {
return (
<View>
<Text > {this.state.text} </Text>
<Button onPress={this.props.navigation.navigate('Home')}
title = "Go Home" />
</View>
);
}
I solved it with the following code, but I don't understand why the previous did'nt work.
render () {
return (
<View>
<Text > {this.state.text} </Text>
<Button onPress={() => this.props.navigation.navigate('Home')}
title = "Go Home" />
</View>
);
}
Could you explain me why the behavior is different ?

When you do:
this.props.navigation.navigate('Home')
You are calling the navigate function and passing it's output to the onPress.
When you do:
() => {
this.props.navigation.navigate('Home')
}
you are passing an arrow function (not a call) and this function contains a call to your navigate, but the arrow function isn't called until the button is pressed.
Your solution with the use of an arrow function is the right thing to do, because you have to pass a parameter, if you didn't have to pass it you could do:
<Button onPress={this.someOfMyFunctions.bind(this)}
title = "Go Home" />
This would result in the someOfMyFunction call when the button is clicked.

That happens because you are actually calling the function in the first case.
In your second code block you are passing the function to the onClick handler which is what you want to do. The value should be a function, not a call to a function.
Hope that helps.

Related

Change value of a state with 3 different buttons (React Native)

How can I dynamically change the value of a state when I click on one of the 3 buttons that I have, for example, I have button 1 with the value: 'State1' and I have button 2 with the value: 'state2', how can I do it? that when clicking on button one, the state takes the value of button 1 and when clicking on button 2, that state is replaced with the value of button 2, is this possible? Any help would be amazing!
Yes. It's possible.
When you press the buttons, they invoke onPress function.
You can use setState function inside the onPress.
Going off your answer, it is only a matter of using the correct props (usually onPress for buttons) and updating your state's initial value.
enum ReadLevel {
Beginner = 'Beginner (1 to 6)',
Intermediate = 'Intermediate (6 to 9)'
}
export function YourComponent() {
const [readLevel, setReadLevel] = useState(ReadLevel.Beginner);
return (
<Fragment>
<TouchableWithoutFeedback onPress={() => setReadLevel(ReadLevel.Beginner)}>
<Text>
{ReadLevel.Beginner}
</Text>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback onPress={() => setReadLevel(ReadLevel.Intermediate)}>
<Text>
{ReadLevel.Intermediate}
</Text>
</TouchableWithoutFeedback>
</Fragment>
);
}

How to show Modal to user before changing routes in React Navigation

So I'm wondering if I'm just not using the right vocabulary in my search - but what I thought might be cool for an app I'm working on would be:
A user starts editing their post.
In case they go back or press a tab to go to another page before
they press "Update".
The screen change is intercepted and a modal shows up and asks if
they want to keep their changes.
I know you can add event handlers - https://reactnavigation.org/docs/navigation-events/ but I'm not sure if these are what I need, I've tested and the prevent default didn't seem to do what I thought it would. That and I couldn't find a way to find what the next intended route that the app would need to go to once they have said "Dismiss" on the modal.
Could anyone point me in the right direction please?
you can create your own modal and back button so you can control what each item do
this.state={
modalConfirm: false
}
goBack = () => { //your goback function }
cancel = () => { this.setState ({modalConfirm :false})
<View>
<TouchableOpacity onPress={()=> this.setState({modalConfirm: true})>
<Icon name='arrow-left' />
</TouchableOpacity>
<Modal visible={this.state.modalConfirm}>
<Text>Do you want to go back? </Text>
<Button title='Go back' onPress={this.goBack} />
<Button title='No' onPress={this.cancel} />
</Modal>
<View>
//your content
</View>
</View>

How can I set onPress event in a child component?

I have a file called SplashScreen.js with a StackNavigator. Sample code:
Inside my SplashScreen.js I have a component called "Login" and INSIDE Login I have a component called "TouchbleOpacity"
What I need is to change the "onPress" event of my TouchbleOpacity component. So I'll be able to navigate in my Navigator (that are inside my SplashScreen.js). The onPress event should look similar to this: onPress={() => navigation.navigate('TelaCadastrar01')
If there is a better way to change the onPress event of my TouchbleOpacity, please tell me, thanks!
I don't know if this is what you are looking for, but i'll give it a try:
In your Login Component you do:
//first button
<TouchableOpacity onPress={this.props.onPress} >
<Text> ... </Text>
</TouchableOpacity>
//second button
<TouchableOpacity onPress={this.props.onPressButton2} >
<Text> ... </Text>
</TouchableOpacity>
Now you are able to pass any onPress function to your Login Component. e.g.
<Login onPress={() => navigation.navigate('TelaCadastrar01')} onPressButton2={() => console.log('second scene')}/>

TouchableHighlight onPress not working

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.

I know react-native's TextInput has a onsubmit callback function, but how do i actually make that submit button?

I'd like to know how to render this button and if so is it autobound to the text in the input field ?
Basically onSumbitEditing will trigger and event provided when go button is clicked from android soft keyboard as in below example :
<TextInput
style={[styles.zipCode, styles.mainText]}
returnKeyType='My Custom button'
onSubmitEditing={(event) => this.updateText( event.nativeEvent.text
)}/>
in above code snippet :
I have action name is 'My Custom button' which will appera in soft keyboard in android and when you press that the updateText event is tiggered , thats what is the meaning on onSubmitEditing
Note : if physical keyboard is enable in android emulator so onSubmitEditing will not tigger any event since you would not be also to press virtual key which is given name as 'My Custom Button'
You can have something like this :
onSubmitEdit = () => {
// whatever you want to do on submit
}
render() {
return(
<View>
<TextInput
style={styles.input}
textAlign="center"
onSubmitEditing={this.onSubmitEdit} />
<TouchableHighlight onPress={this.onSubmitEdit}>
<Text>Press this button to submit editing</Text>
</TouchableHighlight>
</View>
);
}
The onSubmit callback is called when you hit the done/return/join on the keyboard that pops out