TouchOpacity onPress request is not working with formik and react-native-text-input-mask - react-native

When i tried to login the button is not sending request. On button pree i supposed to console the output. It seems that the onChangeText and onChange is not working correcttly in TextInputMask.
TouchableOpacity tag has onPress event where onPress={()=>formikProps.handleSubmit()} is not triggering the onSubmit props of formik.
Here i'm using yup for validation and Formik for submitting data.
const validationSchema = yup.object().shape({
phoneNumber: yup
.string()
.label("Phone Number")
.required("Phone Number is required."),
password: yup.string().label("Password").required("Password is required."),
});
class Home extends Component {
constructor(props) {
super(props);
this.state = {
username: "",
password: "",
press: false,
ButtonStateHolder: false,
};
}
render() {
return (
<ImageBackground style={{ width: "100%", height: "100%" }} source={bgImg}>
<ScrollView>
<Formik
initialValues={{ phoneNumber: "", password: "" }}
onSubmit={(values, actions) => {
this.setState({
password: values.password,
ButtonStateHolder: true,
});
console.warn(this.state.phoneNumber);
console.warn(this.state.password);
}}
validationSchema={validationSchema}
>
{(formikProps) => (
<React.Fragment>
<View>
<View>
<Text>Phone number</Text>
<TextInputMask
keyboardType="number-pad"
ref={(ref) => (this.phoneField = ref)}
onChangeText={(formatted, extracted) => {
this.setState({
phoneNumber: extracted,
});
}}
onChange={formikProps.handleChange("phoneNumber")}
onBlur={formikProps.handleBlur("phoneNumber")}
placeholder={""}
mask={"([000]) [000] [0000]"}
/>
<Text style={styles.errMsg}>
{formikProps.touched.phoneNumber &&
formikProps.errors.phoneNumber}
</Text>
</View>
<View>
<Text style={styles.formLable}>Password</Text>
<TextInput
onChangeText={formikProps.handleChange("password")}
onBlur={formikProps.handleBlur("password")}
placeholder={""}
returnKeyType={"done"}
autoCapitalize={"none"}
autoCorrect={false}
/>
<Text style={styles.errMsg}>
{formikProps.touched.password &&
formikProps.errors.password}
</Text>
<TouchableOpacity
activeOpacity={0.7}
style={styles.btnEye}
onPress={this.showPass}
>
<Image source={eyeImg} style={styles.iconEye} />
</TouchableOpacity>
</View>
</View>
<View style={styles.loginBottom}>
<TouchableOpacity
style={styles.button}
onPress={() => formikProps.handleSubmit()}
>
<Text style={styles.buttonText}> Login </Text>
</TouchableOpacity>
</View>
</React.Fragment>
)}
</Formik>
</ScrollView>
</ImageBackground>
);
}
}
export default Home;
onPress console log is not printed
Someone please help to solve this issue

Formik will manage the state of inputs for you so you don't need to declare it.
const validationSchema = yup.object().shape({
phoneNumber: yup
.string()
.label("Phone Number")
.required("Phone Number is required."),
password: yup.string().label("Password").required("Password is required."),
});
class Home extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<View>
<ScrollView>
<Formik
initialValues={{ phoneNumber: "", password: "" }}
onSubmit={(values, actions) => {
alert(JSON.stringify(values));
}}
validationSchema={validationSchema}
>
{({handleChange, values, handleSubmit, touched, errors, handleBlur}) => (
<React.Fragment>
<View>
<View>
<Text>Phone number</Text>
<TextInput
keyboardType="number-pad"
onChangeText={handleChange}
onChange={handleChange("phoneNumber")}
onBlur={handleBlur("phoneNumber")}
placeholder={""}
mask={"([000]) [000] [0000]"}
value={values.phoneNumber}
/>
<Text>
{touched.phoneNumber &&
errors.phoneNumber}
</Text>
</View>
<View>
<Text>Password</Text>
<TextInput
onChangeText={handleChange("password")}
onBlur={handleBlur("password")}
placeholder={""}
returnKeyType={"done"}
autoCapitalize={"none"}
autoCorrect={false}
value={values.password}
/>
<Text>
{touched.password &&
errors.password}
</Text>
</View>
</View>
<View >
<TouchableOpacity
onPress={() => handleSubmit()}
>
<Text> Login </Text>
</TouchableOpacity>
</View>
</React.Fragment>
)}
</Formik>
</ScrollView>
</View>
);
}
}
You can also manage the form with the useFormik hook instead of the Formik component
import { useFormik } from 'formik';
const validationSchema = yup.object().shape({
phoneNumber: yup
.string()
.label("Phone Number")
.required("Phone Number is required."),
password: yup.string().label("Password").required("Password is required."),
});
const Home = () => {
const { handleChange, values, handleSubmit, touched, errors, handleBlur } = useFormik({
initialValues: {
phoneNumber: "", password: ""
},
onSubmit: (values, actions) => {
alert(JSON.stringify(values));
},
validationSchema
});
console.log(values);
return (
<View>
<ScrollView>
<View>
<View>
<Text>Phone number</Text>
<TextInput
keyboardType="number-pad"
onChangeText={handleChange}
onChange={handleChange("phoneNumber")}
onBlur={handleBlur("phoneNumber")}
placeholder={""}
mask={"([000]) [000] [0000]"}
value={values.phoneNumber}
/>
<Text>
{touched.phoneNumber &&
errors.phoneNumber}
</Text>
</View>
<View>
<Text>Password</Text>
<TextInput
onChangeText={handleChange("password")}
onBlur={handleBlur("password")}
placeholder={""}
returnKeyType={"done"}
autoCapitalize={"none"}
autoCorrect={false}
value={values.password}
/>
<Text>
{touched.password &&
errors.password}
</Text>
</View>
</View>
<View >
<TouchableOpacity
onPress={() => handleSubmit()}
>
<Text> Login </Text>
</TouchableOpacity>
</View>
</ScrollView>
</View>
);
}
}
Let me know if I misunderstood something or if it helps you

Related

react-native-camera freeze when back on screen

I'm developing an application for a school project, and in this application I have a camera component in each view. When I go back on a view the camera freeze.
There is my code of one view:
class LoginView extends React.Component {
constructor(props) {
super(props);
}
togglePseudo = pseudo => {
const action = {type: 'USER_PSEUDO', value: pseudo};
this.props.dispatch(action);
};
render() {
const {navigate} = this.props.navigation;
const userPseudo = this.props.userPseudo;
return (
<View style={style.mainContainer}>
<RNCamera
style={style.backgroundCamera}
type={RNCamera.Constants.Type.back}
flashMode={RNCamera.Constants.FlashMode.on}
androidCameraPermissionOptions={{
title: "Permission d'utiliser la camera",
message: "L'application necessite l'autorisation de la camera",
buttonPositive: 'Autoriser',
buttonNegative: 'Refuser',
}}
/>
<View style={style.goContainer}>
<TouchableOpacity
style={style.backButton}
onPress={() => navigate('HomeView')}>
<Image source={require('assets/images/back-button.png')} />
</TouchableOpacity>
<View style={style.centeredElements}>
<Text style={style.titleMission}>Mission "Pc"</Text>
<View style={style.modalChoosePseudo}>
<Text style={style.modaltitle}>Choisir un pseudo</Text>
<TextInput
style={style.pseudoInput}
onChangeText={pseudo => this.togglePseudo(pseudo)}
value={userPseudo}
/>
{userPseudo !== '' ? (
<TouchableOpacity
style={style.validateButton}
onPress={() => navigate('InGame')}>
<Text style={style.buttonText}>Valider</Text>
</TouchableOpacity>
) : (
<TouchableOpacity
style={[style.validateButton, style.validateButtonDisabled]}
onPress={() =>
Alert.alert('Alerte', 'Veuillez entrer un pseudo')
}>
<Text
style={[style.buttonText, style.validateButtonDisabled]}>
Valider
</Text>
</TouchableOpacity>
)}
</View>
<Image
style={style.logoDimagine}
source={require('assets/images/logo_title_vertical.png')}
/>
</View>
</View>
</View>
);
}
}
I have already looked for solutions, so I tried what I found.
I've try to use componentDidMount with willFocus and willBlur, but it never detect them :
componentDidMount() {
const {navigation} = this.props;
navigation.addListener('willFocus', () =>
this.setState({focusedScreen: true}),
);
navigation.addListener('willBlur', () =>
this.setState({focusedScreen: false}),
);
}

Navigating back to start screen

I have two different documents with two different screens. After an e-mail validation on the first screen, I'm now able to go to the second screen. However, I want to return to the first screen. None of the mentioned approaches on the React Navigation 5.x documentation works for me.
This is the code on the App.js:
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import firebase from './firebase';
import * as EmailValidator from 'email-validator';
import { HitTestResultTypes } from 'expo/build/AR';
import logo from './assets/Circulo.png';
import AgeInput from './AgeInput';
// Clase que representa el diseño de la pantalla inicial de la app
class HomeScreen extends Component {
state = { username: null, password: null, nonValidInput: null }
_onSubmit = ({ navigation }) =>{
if(EmailValidator.validate(this.state.username) == true) {
this.setState({ nonValidInput: false });
const { username, password } = this.state;
try {
// THIS IS WHERE I GO TO THE SECOND SCREEN
firebase.auth().signInWithEmailAndPassword(this.state.username, this.state.password).then(() => this.props.navigation.navigate('Age'));
} catch {
Alert.alert(
'Error',
'Los datos no son correctos',
[
{ text: 'Ok' }
],
{ cancelable: false }
);
}
} else {
this.setState({ nonValidInput: true });
}
}
render() {
return (
<KeyboardAwareScrollView contentContainerStyle={styles.container} scrollEnabled
enableOnAndroid={true} resetScrollToCoords={{x:0, y:0}}>
<View style={styles.logo}>
<Image source = {logo} style={styles.img}/>
<Text style={styles.textLogoPrimary}>Neuron App</Text>
<Text style={styles.textLogoSecondary}>Test</Text>
</View>
<View style={styles.formElement}>
<Text style={styles.formText}>Correo Electrónico</Text>
<TextInput keyboardType='email-address' placeholder='Email' onChangeText={value => this.setState({ username: value })}
style={styles.formInput} />
{this.state.nonValidInput ? (
<Text style={styles.textAlert}>Correo electrónico no valido.</Text>
) : null}
</View>
<View style={styles.formElement}>
<Text style={styles.formText}>Contraseña</Text>
<TextInput style={styles.formInput} placeholder='Contraseña' onChangeText={value => this.setState({ password: value })}
secureTextEntry={true}/>
</View>
<View style={styles.buttonView}>
<TouchableOpacity style={styles.button} onPress={this._onSubmit}>
<Text style={styles.buttonText}>Iniciar</Text>
</TouchableOpacity>
</View>
</KeyboardAwareScrollView>
);
}
}
const Stack = createStackNavigator();
class App extends Component {
render() {
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown: false}} initialRouteName="Home">
<Stack.Screen name='Home' component={HomeScreen} />
<Stack.Screen name='Age' component={AgeInput} />
</Stack.Navigator>
</NavigationContainer>
);
}
}
and this is the code on the AgeInput.js
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import Home from './App';
class App extends Component { // AgeInput
state = { date: null, edad: null, day: null, month: null, year: null }
_ageCalc = () => {
if(this.state.day < 32 && this.state.day > 0 && this.state.month < 13 && this.state.month > 0 && this.state.year != 0) {
var fecha = Date.parse(this.state.year + '-' + this.state.month + '-' + this.state.day);
var hoy = new Date();
var fechaNacimiento = new Date(fecha);
var edad_ahora = hoy.getFullYear() - fechaNacimiento.getFullYear();
var mes = hoy.getMonth() - fechaNacimiento.getMonth();
if (mes < 0 || (mes === 0 && hoy.getDate() < fechaNacimiento.getDate())) {
edad_ahora--;
}
this.setState({ edad: edad_ahora });
} else {
Alert.alert(
'Error',
'Por favor introduce una fecha valida',
[
{ text: 'Ok' }
],
{ cancelable: false },
);
}
}
render () {
return (
<KeyboardAwareScrollView contentContainerStyle={styles.container} scrollEnabled enableOnAndroid={true}
resetScrollToCoords={{x:0, y:0}}>
<View style={styles.topView}>
// This is the button I press to go back to the first screen
<TouchableOpacity style={styles.img} onPress={() => this.props.navigator.navigate('Home')}>
<Image source={flecha} />
</TouchableOpacity>
<View style={styles.topTextWrapper}>
<Text style={styles.topTextPrimary}>Bienvenido a Neuron</Text>
<Text style={styles.topTextSecondary}>¿O no?</Text>
</View>
</View>
<View style={styles.middleView}>
<Text style={styles.formText}>Fecha de nacimiento</Text>
<View style={styles.formRow}>
<View style={styles.textInputWrapper}>
<TextInput style={styles.formInput} placeholder='DD' keyboardType='number-pad'
onChangeText={ value => this.setState({ day: value }) }/>
</View>
<View style={styles.textInputWrapper}>
<TextInput style={styles.formInput} placeholder='MM' keyboardType='number-pad'
onChangeText={ value => this.setState({ month: value }) }/>
</View>
<View style={styles.textInputWrapper}>
<TextInput style={styles.formInput} placeholder='AA' keyboardType='number-pad'
onChangeText={ value => this.setState({ year: value }) }/>
</View>
</View>
</View>
<View style={styles.buttonView}>
<TouchableOpacity style={styles.button} onPress={this._ageCalc}>
<Text style={styles.buttonText}>CALCULAR EDAD</Text>
</TouchableOpacity>
</View>
<View style={styles.ageView}>
<Text style={styles.ageTextPrimary}>Tu edad es:</Text>
<Text style={styles.ageNumber}>{this.state.edad}</Text>
<Text style={styles.ageTextSecondary}>Años</Text>
</View>
</KeyboardAwareScrollView>
);
}
}
export default App; // AgeInput
Thanks for your help
You can do something like this...
render () {
const { navigate } = props.navigation;
//function to go to next screen
goToNextScreen = () => {
return navigate('Home');
return (
<KeyboardAwareScrollView contentContainerStyle={styles.container} scrollEnabled enableOnAndroid={true}
resetScrollToCoords={{x:0, y:0}}>
<View style={styles.topView}>
// This is the button I press to go back to the first screen
<TouchableOpacity style={styles.img} onPress={() => this.goToNextScreen()}>
<Image source={flecha} />
</TouchableOpacity>
<View style={styles.topTextWrapper}>
<Text style={styles.topTextPrimary}>Bienvenido a Neuron</Text>
<Text style={styles.topTextSecondary}>¿O no?</Text>
</View>
</View>
<View style={styles.middleView}>
<Text style={styles.formText}>Fecha de nacimiento</Text>
<View style={styles.formRow}>
<View style={styles.textInputWrapper}>
<TextInput style={styles.formInput} placeholder='DD' keyboardType='number-pad'
onChangeText={ value => this.setState({ day: value }) }/>
</View>
<View style={styles.textInputWrapper}>
<TextInput style={styles.formInput} placeholder='MM' keyboardType='number-pad'
onChangeText={ value => this.setState({ month: value }) }/>
</View>
<View style={styles.textInputWrapper}>
<TextInput style={styles.formInput} placeholder='AA' keyboardType='number-pad'
onChangeText={ value => this.setState({ year: value }) }/>
</View>
</View>
</View>
<View style={styles.buttonView}>
<TouchableOpacity style={styles.button} onPress={this._ageCalc}>
<Text style={styles.buttonText}>CALCULAR EDAD</Text>
</TouchableOpacity>
</View>
<View style={styles.ageView}>
<Text style={styles.ageTextPrimary}>Tu edad es:</Text>
<Text style={styles.ageNumber}>{this.state.edad}</Text>
<Text style={styles.ageTextSecondary}>Años</Text>
</View>
</KeyboardAwareScrollView>
);
}
}
export default App;
Just replace this :
// This is the button I press to go back to the first screen
<TouchableOpacity style={styles.img} onPress={() => this.props.navigator.navigate('Home')}>
with
// This is the button I press to go back to the first screen
<TouchableOpacity style={styles.img} onPress={() => this.props.navigation.navigate('Home')}>
Hope it help.s

Change TextInput editable attribute when I press a button (Not working)

I am trying to change editable with state with the click of a button, but it is not working for some reason. I have seen other people do it this way and it works. Is there another way to do this instead? or am i missing something? Thanks
`class Settings extends Component {
constructor(props) {
super(props);
this.state = {
editable: false,
name: '',
};
this.handleEdit = this.handleEdit.bind(this);
this.handleName = this.handleName.bind(this);
}
handleEdit() {
this.setState({
editable: !this.state.editable,
});
}
handleName = (text) => {
this.setState({
name: text,
});
};
render() {
return(
<View style={styles.container}>
<View style={styles.headerContainer}>
<Text style={styles.header}>Settings</Text>
</View>
<View style={styles.section}>
<View style={styles.sectionTitleContainer}>
<Text style={styles.sectionTitle}>My Account</Text>
</View>
<View>
<Text>Name:</Text>
<TextInput
placeholder="name"
value={this.state.name}
onChangeText={this.handleName}
editable={this.state.editable}
/>
</View>
<View>
<TouchableOpacity onPress={() => this.handleEdit}>
<Text>Edit</Text>
</TouchableOpacity>
</View>
</View>
</View>
);
}
}
export default Settings;`
Change your
<TouchableOpacity onPress={() => this.handleEdit}>
To
<TouchableOpacity onPress={this.handleEdit}>
I believe that since you already binded 'this' to the handleEdit function you dont need to pass the () => anymore.

React-Native _this5.setState is not a function when changing the text in TextInput?

I am currently learning React-Native so apologies if the answer has appeared else where. But in my app whenever I change the text in the TextInput the program will crash with the error _this5.setState is not a function
i.e. if I search for 'Hello', everything works fine. But the moment when I change 'Hello' to 'Hell' the program crashes with that error.
Here's my code
export default class App extends React.Component {
constructor(props){
super(props)
this.state = {
apiKey: 'insertMyAPIKey',
isLoading: true,
text: ''
}
this.setInputState = this.setInputState.bind(this)
}
render() {
return (
<View style={{padding: 10}}>
<TextInput
style={{height: 40}}
placeholder="Search For Summoner!"
value={this.state.text}
onChangeText={(text) => this.setState({
text: text
})}
clearButtonMode="while-editing"
/>
<Button
onPress={() => {
this.MyFunctionsToRun(this.state.text)
}}
title="Search"
color="#841584"
/>
<Text style={{padding: 10, fontSize: 20}}>
Searching for summoner: {this.state.text}
</Text>
<Text>
The summoner ID: {this.state.summonerID}
</Text>
<Text>
The summoner Rank: {this.state.leagueName}, {this.state.tier} {this.state.rank}, {this.state.leaguePoints}
</Text>
<Text>
The Summoner Win Rate: {this.state.winRate}
</Text>
<View>
<FlatList
data={this.state.lastTenGames}
renderItem={({item}) => <Text>{item.lane}</Text>}
/>
</View>
</View>
);
}
}
you can try this
onChangeText={text => (this.state.text = text)}
or use another function
onChangeText={this.changeText}
changeText = text => {
this.setState({text: text});
};
i hope it works for you :D

state disappears when method is call

I'm working on a class project and my state is disappearing. After componentDidMount console.log(this.state) is fine. I initiate setInterval and call inc(). Somehow when I enter inc() the state gets wiped out.
import React from 'react';
import { TextInput,Button,StyleSheet, Text, View } from 'react-native';
import styles from './styles/styles.js';
debug=true
export default class App extends React.Component {
constructor(){
super()
this.state={timer:'WORK',
workTime: 25*60+0,
breakTime: 5*60+0,
currentTime:0,
remainingTime:null,
min:0,
sec:0,
startFlag:false,
resetFlag:false}
}
componentDidMount(){
this.interval=setInterval(this.inc,10000)
if(debug)console.log('COMPONENTDIDMOUNT',this.state)
}
static getDerivedStateFromProps(nextProps, prevState) {
if(debug)console.log('GETDERIVEDSTATEFROMPROPS',prevState)
return null
}
shouldComponentUpdate(nextProps,nextState){
if(debug)console.log('SHOULDCOMPONENTUPDATE',nextState)
return true
}
componentDidUpdate(){
if(debug)console.log('COMPONENTDIDUPDATE',this.state)
}
componentWillUnmount(){
if(debug)console.log('COMMPONENTWILLUNMOUNT',this.state)
}
startToggle(){
if(endTime === null)this.setState({remainingTime:this.state.workTime,
startFlag:!this.state.startToggle})
else this.setState({remainingTime:!this.state.startFlag})
}
textTime(){
let min = Math.floor(this.state.remainingTime / 60).toString()
let sec = (this.state.remainingTime % 60)
if (sec < 10)sec ? '0' + sec : sec.toString()
this.setState({min:min,sec:sec})
}
inc(){
console.log(this.state)
}
captureInput(){}
render() {
console.log('RENDER',this.state)
return (
<View style={styles.container}>
<Text style={styles.bigFont}>{`${this.state.timer + 'TIMER'}`}</Text>
<Text style={styles.bigFont}>12:00</Text>
<View style={styles.button}>
<Button title='START' onPress={()=>this.startToggle()} />
<Button title='RESET' onPress={()=>this.resetToggle()} />
</View>
<View style={styles.row}>
<Text style={[styles.bold,{marginRight:10},{width:112},
{textAlign:'right'}]}>
'Work Timer:'</Text>
<Text style={styles.bold}> min:</Text>
<TextInput
defaultValue='50'
style={styles.input}
onChangeText={(text) => {this.captureInput(text)}}
/>
<Text style={styles.bold}> sec:</Text>
<TextInput
defaultValue='50'
style={styles.input}
onChangeText={(text) => {this.captureInput(text)}}
/>
</View>
<View style={styles.row}>
<Text style={[styles.bold,{marginRight:10},{width:112},
{textAlign:'right'}]}>
'Break Timer:'</Text>
<Text style={styles.bold}> min:</Text>
<TextInput
defaultValue='50'
style={styles.input}
onChangeText={(text) => {this.captureInput(text)}}
/>
<Text style={styles.bold}> sec:</Text>
<TextInput
defaultValue='50'
style={styles.input}
onChangeText={(text) => {this.captureInput(text)}}
/>
</View>
</View>
)
}
}
You have 2 options:
Change inc() to inc = () =>
or
Change this.inc to this.inc.bind(this)
Change your inc method declaration to
inc = () => {
...
}
As per your code, this inside inc() is not referring to the component, hence you are not getting state either.
Hope this will help!