onChange text is not updating its state - react-native

import React, { Component } from 'react';
import { Text, View, TextInput, Button, Alert } from 'react-native';
import datum from './data';
export default class Signup extends React.Component {
constructor(props) {
super(props);
this.state = { name: 'sff', number: '' };
}
signupPressed = () => {
const { name } = this.state;
console.log('checkss', name);
};
render() {
return (
<View
style={{
flex: 1,
flexDirection: 'column',
justifyContent: 'space-evenly',
alignItems: 'center',
}}>
<TextInput
style={{
height: 40,
borderColor: 'gray',
borderWidth: 1,
width: '50%',
}}
onChangeText={TextInputValue => this.setState({ name })}
placeholder="Name"
/>
<TextInput
style={{
height: 40,
borderColor: 'gray',
borderWidth: 1,
width: '50%',
}}
onChangeText={text => this.setState({ name })}
placeholder="Mobile no"
/>
<Button
onPress={this.signupPressed}
title="Signup"
color="#841584"
accessibilityLabel="Learn more about this purple button"
/>
</View>
);
}
}
I have Text input but the onChangeText props is not working as it is
Expected behavior
Has to log the updated name value from the state when the button is clicked
Reality
when I click the button it logs me "checkss" only, not the name value
What is strange here!!
when I click the button for the first time it logs me "checkss,sff" but, when I click it for the second time it shows checkss only

That's because in onChangeText you'll need to do this,
onChangeText={value=>{this.setState({stateVariable:value})}};

<TextInput
value={this.state.name}
style={{height: 40, borderColor: 'gray', borderWidth: 1,width:'50%'}}
onChangeText={(name) => this.setState({name})}
placeholder="Name"
/>
Try above code it will work for you

<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1,width:'50%'}}
onChangeText={(text) => this.setState({name: text })}
placeholder="Name"
/>

Your code fails because you made a mistake when you declare de arrow function
onChangeText={TextInputValue => this.setState({name})}
It must be
onChangeText={TextInputValue => this.setState({ name: TextInputValue })}
Using Ecma6 can be simplified as
onChangeText={name => this.setState({ name })}
To avoid performance issues it is recommended not to use an inline function because is instantiated in all the render cycles. Is better if you create a class method and use it by reference.
export default class Signup extends React.Component {
constructor(props) {
super(props)
this.state = {name:"sff",number:""};
this.handleChange = this.handleChange.bind(this);
}
handleChange(name) {
this.setState({ name });
}
render() {
/* rest of code omitted */
<TextInput
style={
{ height: 40, borderColor: 'gray', borderWidth: 1,width:'50%' }
}
onChangeText={this.handleChange}
placeholder="Mobile no"
/>
/* rest of the code omitted */
}
}

Related

How to focus one textinput per time in react-native?

I have 3 different textinput, textinput1, textinput2 and textinput 3.
I want that when i click on textinput1 that his bordercolor be blue, i did that and works.
What i want now is, when i click on textinput2 to textinput1 be back to his orignal color and the textinput2 be blue now.
Example on the photo.
Example
This is my code:
state = { isFocused: true };
onFocusChange = () => {
this.setState({ isFocused: false });
}
render() {
return (
<View style={styles.container}>
<Text style={styles.headline}>Website ou App</Text>
//TEXTINPUT1
<TextInput
onFocus={this.onFocusChange}
style={(this.state.isFocused) ? {marginTop: 5, height: 40, borderWidth: 2, borderRadius: 5, borderColor: 'gray'} : {marginTop: 5, height: 40, borderWidth: 2, borderRadius: 5, borderColor: '#00b7eb'}}
onChangeText={(text) => this.setState({ site: text })}
value={this.state.site}
//TEXTINPUT2
<Text style={styles.headline}>Utilizador/Email</Text>
<TextInput
style={{ marginTop: 5, height: 40, borderColor: 'gray', borderWidth: 1 }}
onChangeText={(text) => this.setState({ local: text })}
value={this.state.local}
/>
Some idea how i can do that? Thank you.
Sharing my same answer from here.
Set up your text inputs and their styles in a component. Then use state in the component to control your styles.
const [focus, setFocus] = useState(false);
<TextInput
style={focus ? styles.inputOnFocus : styles.inputOnBlur}
onFocus={() => setFocus(true)}
onBlur={() => setFocus(false)}
/>
Styles:
const styles = StyleSheet.create({
inputOnFocus: { borderColor: '#C0C0C0' },
inputOnBlur: { borderColor: '#4b6cd5' }
});
One option is to track the name of the focused TextInput. You'll need to make sure to use the updater version of setState in the blur event to avoid race conditions between the onBlur and onFocus methods of the two inputs:
state = { focusedInput: null };
onFocusChange = (inputName) => {
this.setState({focusedInput: inputName});
}
onBlurChange = (inputName) => {
this.setState(state => {
if (state.focusedInput === inputName) {
return {focusedInput: null};
}
// no change if some other input already has focus
return null;
}
}
render() {
return (
<View style={styles.container}>
<Text style={styles.headline}>Website ou App</Text>
//TEXTINPUT1
<TextInput
onFocus={() => this.onFocusChange("input1")}
onBlur={() => this.onBlurChange("input1")}
style={(this.state.focusedInput === "input1") ? {marginTop: 5, height: 40, borderWidth: 2, borderRadius: 5, borderColor: 'gray'} : {marginTop: 5, height: 40, borderWidth: 2, borderRadius: 5, borderColor: '#00b7eb'}}
onChangeText={(text) => this.setState({ site: text })}
value={this.state.site} />
Repeat for other inputs with a name different than "input1".
I think the easiest way to do it is just to create your own custom component to handle the border line. I have created a expo snack for you to see a workaround (other than the mentioned before). https://snack.expo.io/#ianvasco/e8efb0.
Anyway here is the code.
//somefile.js
import React, {useState} from 'react';
import { Text, View, StyleSheet, TextInput } from 'react-native';
import Constants from 'expo-constants';
export default App = () => {
const [isInputFocused, setInputFocused] = useState({input1: false, input2: false})
return (
<View style={styles.container}>
<TextInput
onFocus={() => setInputFocused((prev) => ({...prev, input1: true}))}
onBlur={() => setInputFocused((prev) => ({...prev, input1: false}))}
style={isInputFocused.input1 ? styles.input : styles.inputFocused }
onChangeText={() => {}}/>
<TextInput
style={isInputFocused.input2 ? styles.input : styles.inputFocused }
onChangeText={() => {}}
onFocus={() => setInputFocused((prev) => ({...prev, input2: true}))}
onBlur={() => setInputFocused((prev) => ({...prev, input2: false}))}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
inputFocused: {
marginTop: 5,
height: 40,
borderWidth: 2,
borderRadius: 5,
borderColor: 'grey'
},
input: {
marginTop: 5,
height: 40,
borderWidth: 2,
borderRadius: 5,
borderColor: '#00b7eb'
}
});
Also, I just added React Hooks. I encourage you to use them, since the code get simplified a lot. Here is more about Hooks
Create Custom TextInput component which will set "borderColor" to "black" or "blue" in component with help of "onFocus" and "onBlur" events. In this way you can use multiple TextInputs without any conditions in parent
Sample Code
import React from "react";
import { SafeAreaView, TextInput, Text } from "react-native";
class CustomTextInput extends React.Component {
state = { hasFocus: false };
_onFocus = () => {
this.setState({ hasFocus: true });
};
_onBlur = () => {
this.setState({ hasFocus: false });
};
render() {
const borderColor = this.state.hasFocus ? "blue" : "black";
return (
<TextInput
style={{ padding: 16, borderColor: borderColor, borderWidth: 1 }}
onFocus={this._onFocus}
onBlur={this._onBlur}
/>
);
}
}
export default class App extends React.Component {
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<Text style={{ marginTop: 16, textAlign: "center" }}>Website App</Text>
<CustomTextInput />
<Text style={{ marginTop: 16, textAlign: "center" }}>Email</Text>
<CustomTextInput />
<Text style={{ marginTop: 16, textAlign: "center" }}>Password</Text>
<CustomTextInput />
</SafeAreaView>
);
}
}
App Preview
**We can control the multiple text input by using Switch case and method **
_onFocusTo=(data)=>{
const {
overdueAmount,
bounceCharges,
penalInterest,
overdueCharges,
collectionPickupCharge,
ebcCharges,
foreClosureAmount,
amount,
} = this.state;
console.log("focus");
switch(data) {
case 1:{
if(amount === "0"){
this.setState({amount:""})
}
}break;
case 2:{
if(bounceCharges === "0"){
this.setState({bounceCharges:""})
}
}break;
case 3:{
if(penalInterest === "0"){
this.setState({penalInterest:""})
}
}break;
case 4:{
if(foreClosureAmount === "0"){
this.setState({foreClosureAmount:""})
}
}break;
case 5:{
if(ebcCharges === "0"){
this.setState({ebcCharges:""})
}
}break;
case 6:{
if(collectionPickupCharge === "0"){
this.setState({collectionPickupCharge:""})
}
}break;
}
}
/In Textinput make function and pass it to onFocus
<TextInput
underlineColorAndroid="transparent"
style={styles.textInput1}
placeholder={""}
placeholderTextColor={Colors.labelTextColor1}
keyboardType={"numeric"}
onFocus={() => this._onFocusTo(1)}
onBlur={this.addTotal}
onChangeText={(amount) => this.setAmountDes(amount)}
value={this.state.amount}
/>
<TextInput
underlineColorAndroid="transparent"
style={styles.textInput1}
placeholder={""}
placeholderTextColor={Colors.labelTextColor1}
onFocus={() => this._onFocusTo(2)}
onBlur={this.addTotal}
keyboardType={"numeric"}
onChangeText={(bounce) => this.setBounce(bounce)}
value={this.state.bounceCharges}
/>
<TextInput
underlineColorAndroid="transparent"
style={styles.textInput1}
placeholder={this.state.penalInterest}
placeholderTextColor={Colors.labelTextColor1}
onFocus={() => this._onFocusTo(3)}
onBlur={this.addTotal}
keyboardType={"numeric"}
onChangeText={(penal) => this.setPenal(penal)}
value={this.state.penalInterest}
/>
....continues

How can I activate a button that is inside a NavigationOptions when I write in a text input in react navigation?

Very good, I am new to react native and I am trying to make a survey application in which I want to add a "next" button to my header and that can only be clicked or rather activated when I enter a character in a text input that will be in the center of the screen, so far what I did was the button and go to another screen with NavigationOptions but I can not do the other thing if someone knows would help me a lot of thanks.
import React, { Component } from "react";
import {
View,
Text,
StyleSheet,
TouchableOpacity,
Image,
TextInput
} from "react-native";
class Screen1 extends Component {
static navigationOptions = ({ navigation }) => ({
headerTitle: (
<Image
source={require('../Icons/icon3.png')}
style={{ width: 35, height: 35, marginLeft: 10 }}
/>
),
headerRight: (
<View>
<TouchableOpacity
disabled={Idonotknowhowtodoit}
onPress={() => navigation.navigate('Screen2')}
style={styles.Btn}>
<Text
style={styles.TxtBtn}>Next</Text>
</TouchableOpacity>
</View>
),
});
render() {
return (
<View style={styles.container}>
<TextInput
type="text"
placeholder="Enter Text"
/>
</View>
);
}
}
export default Screen1;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
},
Btn: {
marginRight: 5,
justifyContent: 'center',
borderWidth: 2,
borderColor: '#000',
borderRadius: 2,
backgroundColor: '#000',
padding: 4
},
TxtBtn: {
textAlign: 'center',
color: '#fff',
fontSize: 14,
fontWeight: 'bold'
}
});
you can use params to check button is disable or active in navigationOptions.
class Screen1 extends Component {
constructor(props) {
super(props);
this.state = {
text: ''
};
}
static navigationOptions = ({ navigation }) => ({
headerTitle: (
<Image
source={require('../Icons/icon3.png')}
style={{ width: 35, height: 35, marginLeft: 10 }}
/>
),
headerRight: (
<View>
<TouchableOpacity
disabled={navigation.getParam('isDisable')} // get value from params and pass it to disabled props
onPress={() => navigation.navigate('Screen2')}
style={styles.Btn}>
<Text
style={styles.TxtBtn}>Next</Text>
</TouchableOpacity>
</View>
),
});
// set by a default value in componentDidMount to make the next button disable initially
componentDidMount() {
this.props.navigation.setParams({ isDisable: true });
}
render() {
return (
<View style={styles.container}>
<TextInput
type="text"
placeholder="Enter Text"
value={this.state.text} //set value from state
onChangeText={(text) => {
//when text length is greater than 0 than next button active otherwise it will be disable
let isDisable = text.length > 0 ? false : true
//set value in the state
this.setState({
text: text
})
// set value to params
this.props.navigation.setParams({ isDisable: isDisable});
}
}
/>
</View>
);
}
}

React Native : Arranging elements

I am building a very simple app with a picker and two inputs/labels.
It currently looks like this in my iphone.
This is my code
import React from 'react';
import { StyleSheet, Text, View, Button, Modal, TextInput, Picker } from 'react-native';
export default class App extends React.Component {
constructor(props) {
super(props);
}
state = {
b1text: 'Kg',
b2text: 'Cm',
weight: '',
height: '',
standard: 'Metric'
}
render() {
return (
<View style={styles.container}>
<Picker
selectedValue={this.state.standard}
onValueChange={(itemValue, itemIndex) => {
this.setState({standard: itemValue});
if(itemValue === "Metric") {
this.setState({b1text: "Kg"});
this.setState({b2text: "Cm"});
}
if(itemValue === "Imperial") {
this.setState({b1text: "Lbs"});
this.setState({b2text: "Inches"});
}
} }
style={{height: 100, width: 100 }}
>
<Picker.Item label="Metric" value="Metric" />
<Picker.Item label="Imperial" value="Imperial" />
</Picker>
<TextInput
style={{height: 40, width: 60, borderColor: 'gray', borderWidth: 1}}
onChangeText={(text) => this.setState({text: weight})}
value={this.state.weight}
/>
<Text>{this.state.b1text}</Text>
<TextInput
style={{height: 40, width: 60, borderColor: 'gray', borderWidth: 1}}
onChangeText={(text) => this.setState({text: height})}
value={this.state.height}
/>
<Text>{this.state.b2text}</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
},
});
But I want it to look something like this as shown below.
I have tried margin, padding etc. Still no luck.
Can someone tell me what css/flex property I can use to change the UI like how I want ?
I've created an Expo Snack that has a closer example of the UI you want to achieve. But I'll leave it to you to work out the details.
import React from 'react';
import { StyleSheet, Text, View, TextInput, Picker } from 'react-native';
export default class App extends React.Component {
constructor(props) {
super(props);
}
state = {
b1text: 'Kg',
b2text: 'Cm',
weight: '',
height: '',
standard: 'Metric',
};
render() {
return (
<View style={styles.container}>
<View style={styles.top}>
<Picker
selectedValue={this.state.standard}
onValueChange={itemValue => {
this.setState({ standard: itemValue });
if (itemValue === 'Metric') {
this.setState({ b1text: 'Kg' });
this.setState({ b2text: 'Cm' });
}
if (itemValue === 'Imperial') {
this.setState({ b1text: 'Lbs' });
this.setState({ b2text: 'Inches' });
}
}}>
<Picker.Item label="Metric" value="Metric" />
<Picker.Item label="Imperial" value="Imperial" />
</Picker>
</View>
<View style={styles.bottom}>
<TextInput
style={{
height: 40,
width: 60,
borderColor: 'gray',
borderWidth: 1,
}}
onChangeText={() => this.setState({ text: weight })}
value={this.state.weight}
/>
<Text>{this.state.b1text}</Text>
<TextInput
style={{
height: 40,
width: 60,
borderColor: 'gray',
borderWidth: 1,
}}
onChangeText={() => this.setState({ text: height })}
value={this.state.height}
/>
<Text>{this.state.b2text}</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
top: {
width: '100%',
flex: 1,
},
bottom: {
flex: 1,
alignItems: 'center',
},
});
One of the crucial things you need to is learn how to write styles with react-native. Here is a resource that has a guide of all of the style properties you can use with const {StyleSheet} from 'react-native'.
https://github.com/vhpoet/react-native-styling-cheat-sheet
Good luck :)

Cannot Store and Retrieve data using AsyncStorage in React native

I am new to react native,I was just learning react native now,i was trying to store values from TextInput and store into AsyncStorage by clicking Register Button.I am trying to get that value by clicking Get Button.I can't get value from AsyncStorage.getItem('value'), later I was thought wether data is storing in AsyncStorage.setItem('name','value').Somebody look at this code and tell me the answer where i was made mistake.
export default class AsyncStorageEample extends Component
{
constructor(props)
{
super(props)
this.state= { name:'', email:'',mobile:''}
this.onRegisterPress=this.onRegisterPress.bind(this)
this.onRetreive=this.onRetreive.bind(this)
}
onRegisterPress()
{
let name=this.state.name
let email=this.state.email
let mobile=this.state.mobile
AsyncStorage.setItem('name',name)
AsyncStorage.setItem('email',email)
AsyncStorage.setItem('mobile',mobile)
this.setState({name: name, email:email,mobile:mobile})
}
onRetreive()
{
var user;
user= AsyncStorage.getItem('name').then((value) => this.setState({ 'name': value }))
Alert.alert('Name:'+user);
}
render() {
return (
<View style={styles.container}>
<View style={styles.Signupform}>
<Text style={styles.textStyle}> Name </Text>
<TextInput style={styles.tInRegister} onChangeText={(text)=> this.setState({name: text})} value = {this.state.name}/>
<Text style={styles.textStyle}> Email </Text>
<TextInput style={styles.tInRegister} onChangeText={(text)=> this.setState({email: text})} value= {this.state.email} />
<Text style={styles.textStyle}> Mobile </Text>
<TextInput style={styles.tInRegister} onChangeText={(text)=> this.setState({mobile: text})} vaue= {this.state.mobile} />
<Button
onPress={this.onRegisterPress.bind(this)}
title="Register"
color="#841584"
/>
<Button
style={styles.get}
onPress={this.onRetreive.bind(this)}
title="Get"
color="#841584"/>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
tInRegister: {
fontSize: 16,
height: 40,
color: '#800080'
},
textStyle: {
fontSize: 16,
color: '#800080'
},
Signupform: {
width: 400,
height: 100,
justifyContent: 'center',
marginTop: 10,
marginLeft: 10,
marginRight: 10
},
get:
{
marginTop:20,
},
});
AppRegistry.registerComponent('AsyncStorageEample', () => AsyncStorageEample);
AsyncStorage is an asynchronous operation. So it should be done with 'async - await' .
Try the following code
async onRetreive() {
const user = await AsyncStorage.getItem('name');
Alert.alert('Name:'+user);
}

How to validate email and password on click of submit button in React native?

I'm new to react-native and by following the docs I have created a simple login screen. Now I'm not getting how to validate input fields on click of submit button. Below is the code for login screen.
import React, { Component } from 'react';
import {
AppRegistry,
Text,
Image,
View,
Button,
StyleSheet,
TextInput,
Linking,
Alert
} from 'react-native';
class LoginPage extends Component {
//On click of submit button alert will appear
_onSubmit() {
Alert.alert('Button has been pressed!');
}
render() {
return (
<View style={styles.containerView}>
<Text style={styles.loginText} >
Username or Email
</Text>
<TextInput style={styles.inputFields}
placeholder="e.g: abc#example.com" />
<Text style={styles.loginText}>
Password
</Text>
<TextInput style={styles.inputFields}
placeholder="Password"
secureTextEntry={true} />
<Text style={{color: 'blue', marginBottom: 10}}
onPress={() => Linking.openURL('https://www.google.co.in')}>
Forgot Password?
</Text>
<Button
onPress={this._onSubmit}
title="Login"
style={styles.loginButton}
accessibilityLabel="Ok, Great!"
/>
</View>
);
}
};
//Stylesheet for input fields
const styles= StyleSheet.create({
containerView: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ffebcd',
borderStyle: 'solid',
borderColor: '#000000'
},
loginText: {
fontSize: 20,
marginBottom: 10
},
inputFields: {
fontSize: 20,
borderStyle: 'solid',
borderColor: '#000000',
borderRadius: 30,
marginBottom: 10
},
loginButton: {
backgroundColor: '#34A853'
}
});
AppRegistry.registerComponent('AwesomeProject', () => LoginPage);
import React, { Component } from 'react';
import {
AppRegistry,
Text,
Image,
View,
Button,
StyleSheet,
TextInput,
Linking,
Alert
} from 'react-native';
class LoginPage extends Component {
state = {
username: null,
password: null
}
//On click of submit button alert will appear
_onSubmit() {
const { username, password } = this.state;
Alert.alert('Button has been pressed!');
}
render() {
return (
<View style={styles.containerView}>
<Text style={styles.loginText} >
Username or Email
</Text>
<TextInput style={styles.inputFields}
onChangeText={value => this.setState({ username: value })}
placeholder="e.g: abc#example.com" />
<Text style={styles.loginText}>
Password
</Text>
<TextInput style={styles.inputFields}
onChangeText={value => this.setState({ password: value })}
placeholder="Password"
secureTextEntry={true} />
<Text style={{color: 'blue', marginBottom: 10}}
onPress={() => Linking.openURL('https://www.google.co.in')}>
Forgot Password?
</Text>
<Button
onPress={this._onSubmit}
title="Login"
style={styles.loginButton}
accessibilityLabel="Ok, Great!"
/>
</View>
);
}
};
//Stylesheet for input fields
const styles= StyleSheet.create({
containerView: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ffebcd',
borderStyle: 'solid',
borderColor: '#000000'
},
loginText: {
fontSize: 20,
marginBottom: 10
},
inputFields: {
fontSize: 20,
borderStyle: 'solid',
borderColor: '#000000',
borderRadius: 30,
marginBottom: 10
},
loginButton: {
backgroundColor: '#34A853'
}
});
AppRegistry.registerComponent('AwesomeProject', () => LoginPage);
basically working with forms in react native is somewhat challenging. If you want some mature solution I would suggest to take a look at tcomb-form-native
If you want to keep things simple, then you have to store references to your inputs and then (for example on onSubmitEditing) you can get entered value and validate it by yourself.
You can use this.state.username for validation
<TextField label={'Username'} onChangeText={(username)=>this.setState({username})} value={this.state.username} />