onChangeText of InputField issue in React Native - react-native

I am working on a ReactNative application. I have some input fields, on button click if any of these fields is empty i have to show validation error. My code is:
<View>
<InputField placeholder="Teilnummer"
onChangeText={(nm)=> this.setState({pTeilnummer: nm})}
/>
<View>
{
this.state.ErrorTeilnummer ? <Text style={styles.ValidationErrorMessage}> * Required </Text> : null
}
</View>
<InputField placeholder="Teilbenennung"
onChangeText={(nm)=> this.setState({pTeilbenennung: nm})}
/>
<View>
{
this.state.ErrorTeilbenennung ? <Text style={styles.ValidationErrorMessage}> * Required </Text> : null
}
</View>
<InputField placeholder="Lieferant"
onChangeText={(nm)=> this.setState({pLieferant: nm})}
/>
<View>
{
this.state.ErrorLieferant ? <Text style={styles.ValidationErrorMessage}> * Required </Text> : null
}
</View>
<Button title="Speichern" color="#ee7100" onPress={() => { this._addProject(this.state.pTeilnummer + "_" + this.state.pTeilbenennung + "_" + this.state.pLieferant, this.state.pdate)}}/>
</View>
I have declared these states as:
constructor(props){
this.state = {ErrorTeilbenennung: false, ErrorTeilnummer: false, ErrorLieferant: false pTeilbenennung: null, pTeilnummer: null, pLieferant: null};
My button click code is:
_addProject = (name, date) =>{
teilbenennung = this.state.pTeilbenennung;
teilnummer = this.state.pTeilnummer;
lieferant = this.state.pLieferant;
var selectedCheck = this.state.addCheck
if(teilbenennung == null || teilnummer == null || lieferant == null)
{
if(teilbenennung == null)
this.setState({ErrorTeilbenennung: true})
else
this.setState({ErrorTeilbenennung: false})
if(teilnummer == null)
this.setState({ErrorTeilnummer: true})
else
this.setState({ErrorTeilnummer: false})
if(lieferant == null)
this.setState({ErrorLieferant: true})
else
this.setState({ErrorLieferant: false})
}
else
{ // saving to database
}
}
When i click on the button first time i get the required validation errors. But after i type something in the first InputField and presses the button, i still get the validation error against that field (may be there is some issue with "onChangeText"), but if i click the button again then the validation error against that field is removed (i mean i have to click twice). Let me add one more thing, when i click on the InputField to write something in it the component reloads. How can i remove this issue so that it works fine with single click

I made an example to solve your problem. This is how you solve the problem you want.
Comparing the status values separately is a very inconvenient way. We can solve this problem sufficiently through onChangeText
Example is here ExampleLink
import React, { Component } from 'react';
import { AppRegistry, TextInput,View,Text,Button } from 'react-native';
export default class UselessTextInput extends Component {
constructor(props) {
super(props);
this.state = {
text: '',error1 : "error1" ,
text2: '',error2 : "error2" };
}
checkfunc() {
if(this.state.text !== '' && this.state.text2 !== ''){
alert("sucess");
} else {
alert("faild");
}
}
render() {
return (
<View style={{flex:1,alignItems:"center" , justifyContent:"center"}}>
<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1}}
onChangeText={(text) => this.setState({text})}
value={this.state.text}
/>
{this.state.text !== '' ? null : (<Text>{this.state.error1}</Text>)}
<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1}}
onChangeText={(text2) => this.setState({text2})}
value={this.state.text2}
/>
{this.state.text2 !== '' ? null : (<Text>{this.state.error2}</Text>)}
<Button title="checkinput" onPress={() => this.checkfunc()}/>
</View>
);
}
}
// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => UselessTextInput);

Issue was that my view was inside KeyboardAwareScrollView, so the first click closes the keyboard, that's why my button click does not trigger on first click. This can be resolved in two ways:
Use ScrollView instead of KeyboardAwareScrollView
Set keyboardShouldPersistTaps to true like this:
<KeyboardAwareScrollView keyboardShouldPersistTaps={true}>

Related

Switch button in react-native

Hi I have a problem with the switch button in react-native. I'm using it to toggle or not the activation of push notification. The problem is that if I quit the application, the state of the switch is getting back to false, it's not saving the state ? What am I doing wrong ?
Here is my code :
constructor(props) {
super(props)
this.state = {
switchValue:false
}
}
toggleSwitch = (value) => {
this.setState({switchValue: value})
if(this.state.switchValue){
console.log("Unsubscribed")
} else {
console.log("Subscribed")
}
}
render() {
return (
<SafeAreaView>
<ScrollView>
<View style = {styles.view_container}>
<Text style = {styles.titre}>Notifications</Text>
<Text style = {{marginTop:9}}>Permet de recevoir des alertes lorsque de nouvelles vidéos sont disponibles.</Text>
<View style = {{marginTop: 30, justifyContent:"center", alignContent:"center"}}>
<View style = {styles.row}>
<View style = {styles.row_infos}>
<Image source={require('../Images/couleurs/icons8-belier-100.png')} style = {styles.image}/>
<Text style = {{fontWeight:"bold", fontSize:16,lineHeight:16, color:"#7c4dff"}}>Bélier</Text>
</View>
<Switch
onValueChange = {this.toggleSwitchBelier}
value = {this.state.switchValueBelier}
trackColor={{false:'#000000', true:'#7c4dff'}}
/>
</View>
</View>
</View>
</ScrollView>
</SafeAreaView>
)}
When you quit your Application, all saved variables in the state will be "resetted".
If you would like to keep the state of the toggle button, i would recommend you to use the AsyncStorage, provided by expo.
See here:
https://docs.expo.io/versions/v36.0.0/react-native/asyncstorage/
Just set the item when the toggle-function is triggered like this:
import { AsyncStorage } from 'react-native';
AsyncStorage.setItem('buttonToggle', 'true');
And when you start the application again, load the current status from the AsyncStorage:
const value = await AsyncStorage.getItem('buttonToggle');
if (!!value && value === 'true'){
// Do whatever you like
}

Get user input from input field in react similar to getElementById in react native using props

I am doing a loan calculation app and i run into the trouble since i am new to react native and previously i have been manipulating the DOM using querySelector or getElementById functions. However this does not work in react, and i am using state to store the value from the user, but i just can't seem to get it right, What am i doing wrong?
I've inserted the calculation element that is later rendered in app.js. All elements are showing up with no error, but the problem is to get user input data and then be able to use that data and do calculations.
Here is my Class
class LanKalkylElement extends React.Component {
constructor(props) {
super(props);
this.state = {
loanAmount: 20000,
loanInterest: 2.5,
loanYear: 10,
};
}
changeAmount(loanAmount) {
this.setState(() => {
return {
loanAmount: parseFloat(loanAmount),
};
});
}
changeInterest(loanInterest) {
this.setState(() => {
return {
loanInterest: parseFloat(loanInterest),
};
});
}
changeYear(loanYear) {
this.setState(() => {
return {
loanYear: parseFloat(loanYear),
};
});
}
calcButton() {
Alert.alert(this.props.loanAmount);
}
buttonHomeFunc() {
this.props.navigation.navigate('Start');
}
render() {
const {loanAmount, loanInterest, loanYear} = this.state;
return(
<View style={styles.contentStyle}>
<Text style={styles.text}> Lånebelopp </Text>
<TextInput style={styles.numericInput}
onBlur={Keyboard.dismiss}
keyboardType={'numeric'}
value={loanAmount}
onValueChange={this.changeAmount.bind(this)} />
<Text style={styles.text}> Ränta </Text>
<TextInput style={styles.numericInput}
onBlur={Keyboard.dismiss}
keyboardType={'numeric'}
value={loanInterest}
onValueChange={this.changeInterest.bind(this)} />
<Text style={styles.text}> Antal år: {String(loanYear)}</Text>
<Slider step={1}
maximumValue={15}
value={loanYear}
onValueChange={this.changeYear.bind(this)} />
<Button title='Kalkylera' onPress={() => this.calcButton()}/>
<Text style={styles.textResult}>Total summa att återbetala:</Text>
<Text style={styles.textResult}>varav räntekostnad:</Text>
<Button title='Tillbaka' onPress={() => this.buttonHomeFunc()}/>
</View>
)
}
}
export default withNavigation(LanKalkylElement);
When a user changes a value in a text input, onValueChange is called. You have bound this prop to functions that modify the state for this component.
This means the value in the text input will always match the value in the state. Therefore, if you need to access the value in a text input you would simply retrieve it from the state, like this:
const loanAmount = this.state.loanAmount;
doSomethingWithLoanAmount(loanAmount);

Highlight only one button at once (react native)

I currently have three TouchableHighlight buttons and I'd like to keep only one of them highlighted at once and their state stored.
state:
state = {
selected: null,
};
handleClick function
_handleClick(flag) {
if (flag == 1) {
this.setState({selected: true});
}
}
One of the three touchable highlights
<TouchableHighlight
style={styles.container}
onPress={() => this._handleClick('any flag')}
underlayColor="red">
<View>
<Text>
Test
</Text>
</View>
</TouchableHighlight>
So far this only highlights the current button I'm trying to tap for about a second and the underlay colour goes.
Could anyone help me with this?
Thanks
You can try using this:
state:
state = {
selected: null,
SelectedButton: ''
};
handleClick function:
_handleClick(flag, button) {
if (flag == 1) {
this.setState({selected: true});
}
this.setState({SelectedButton: button})
}
Touchable:
<TouchableHighlight
style={styles.container}
onPress={() => this._handleClick('any flag', '1')}
underlayColor="red">
<View style={{backgroundColor: (this.state.SelectedButton === '1' ? 'red' : 'green')}}>
<Text>
Test
</Text>
</View>
</TouchableHighlight>
What it means:
When you press the touchable, the function "handleClick" will not only save the state of the button, but will save the last pressed button too.
And then on the style of the view inside the touchable, here's the magic:
<View`style={{backgroundColor: (this.state.SelectedButton === '1' ? 'red' : 'green')}}>
It means: "If the last selected button it's equals to the atual ID of the button, the color of the view, will be red, otherwise, the color will be green"
You can make this to the others touchables, wich one with your "ID" (1, 2, 3, and so on)
UPDATE:
If each button has a unique value, you can try using:
state:
state = {
selected: null,
value: ''
};
handleClick function:
_handleClick(flag, button) {
if (flag == 1) {
this.setState({selected: true});
}
this.setState({value: 'flag'})
}
Touchable:
<TouchableHighlight
style={[styles.container, { backgroundColor: (this.state.value === 'any flag' ? 'red' : 'green')}]}
onPress={() => this._handleClick('any flag')}
underlayColor="red">
<View>
<Text>
Test
</Text>
</View>
</TouchableHighlight>

How to update useState into TextInput

I have a simple <TextInput> in React Native and i want to print some text when value change. Its working after second character entered, but not, when user press just one char.
I try using functions and even with onChange and take from e.target.value but allways are missing one character at "search" state.
import React, { useState } from 'react';
import { TextInput, View, Text } from 'react-native';
const App = () => {
const [search, setSearch] = useState('');
const [searching, setSearching] = useState(false);
return(
<View>
<TextInput
onChangeText={(value) => {
setSearch(value)
setSearching(search=='' ? false : true)
}}
value = { search }
/>
{
searching ?
(
<Text>Searching</Text>
) : (
<Text>No searching</Text>
)
}
</View>
);
}
export default App
I expect to show "Searching" when TextBox value are not empty.
useState or setState may be asynchronous, so the first time you call setSearch(value), the search state may not be updated yet.
onChangeText={(value) => {
setSearch(value)
setSearching(search == '' ? false : true) // "search" is still previous value
}}
Instead, you can directly use value instead for checking.
onChangeText={(value) => {
setSearch(value)
setSearching(value == '' ? false : true) // value is latest
}}
You need to compare the actual value of the TextInput
Using search=='' ? false : true will check the previous state and won't change
onChangeText={(value) => {
setSearch(value)
setSearching(search=='' ? false : true)
}}
This will check for the changed value.
onChangeText={(value) => {
setSearch(value)
setSearching(value == '' ? false : true) // use value
}}
You need to use value instead of search
Just change this
setSearching(search=='' ? false : true)
to
setSearching(value=='' ? false : true)
After help of both i resolved. This is the code if help to somebody. The idea are a TextInput with a len icon on the left, and when user start to write made the call to Firebase and show a loading icon on the right (spinner).
<Icon
name='search'
size={25}
color={PRIMARY_BACKGROUND_COLOR}
style={styles.searchIcon}
/>
<TextInput
underlineColorAndroid = 'transparent'
style = { styles.textBox }
onChangeText={(value) => { onChangeText(value) }}
value = { search }
placeholder = { i18n.t('Search') }
/>
{
searching ?
(
<TouchableOpacity style = { styles.visibilityBtn }>
<Animatable.View
ref={ref => (this.AnimationRef = ref)}
animation='rotate'
easing='linear'
iterationCount='infinite'
>
<Icon
name='spinner-3'
size={20}
color={PRIMARY_BACKGROUND_COLOR}
/>
</Animatable.View>
</TouchableOpacity>
) : (
<TouchableOpacity onPress={ clearSearch } style = { styles.visibilityBtn }>
<Icon
name='close'
size={20}
color={PRIMARY_BACKGROUND_COLOR}
/>
</TouchableOpacity>
)
}
And the function
const onChangeText = value => {
setSearch(value)
setSearching(value =='' ? false : true)
Helper.getCategoriesSearch(value, (categories) => {
setSearching(false)
//props.searchResults(categories); THIS DO NOT WORK RETURN DATA TO props :(
})
}
Thanks All

Not able to set active and inactive images in React Native

I am showing custom tab-bar in my application which is showing at centre of the screen. So, Each time one tab should be active and other tabs will be inactive state.
According to that, I have implemented logic(bool values) and tried to change images, But, It's not working.
My requirement is
I have 4 tabs, suppose if user tap on 1st tab, I have to set active
image to 1st tab then rest of 3 tabs with inactive images according to
those titles (different inactive) images.
Its like for all tabs active and inactive states, each time one tab
only active state.
It's showing undefined and even if and else if conditions executing, But, nothing changing images.
Here is my code
constructor(props) {
super(props);
// this.state = { dataArray: getListData()}
this.state = { selectedTab: 'Value', flagImage:true, flagForTelugu: false, flagForTamil: false, flagForHindi: false, flagForEnglish: false}
}
OnTabItemHandler = (tabItem) => {
this.setState({selectedTab: tabItem,flagImage:this.state.flagImage})
}
renderBottomContent = (item) => {
const {selectedTab, dataArray, flagForTelugu, flagForTamil, flagForHindi, flagForEnglish} = this.state
this.state = { dataArray: getListData()}
if (selectedTab === ‘Telugu’) {
this.flagForTelugu = true
this.flagForTamil = false
this.flagForHindi = false
this.flagForEnglish = false
} else if (selectedTab === ‘Tamil’) {
this.flagForTamil = true
this.flagForTelugu = false
this.flagForHindi = false
this.flagForEnglish = false
} else if (selectedTab === ‘Hindi’) {
this.flagForHindi = true
this.flagForTamil = false
this.flagForTelugu = false
this.flagForEnglish = false
} else if (selectedTab === ‘English’) {
this.flagForEnglish = true
this.flagForTamil = false
this.flagForTelugu = false
this.flagForHindi = false
}
//loading some other text here in bottom
}
render(item) {
const {selectedTab, flagForTelugu, flagForTamil, flagForHindi, flagForEnglish} = this.state;
return (
<View style={styles.container}>
<View style = {styles.tabContainer}>
<TouchableOpacity style={styles.tabIcons} onPress={() => this.OnTabItemHandler(‘Telugu’)}>
<Image
style={styles.tabItemsImages}
source={this.state.flagImage === true ?
teluguActiveImage :
teluguDeActiveImage}
/>
</TouchableOpacity>
<Text style={styles.tabTextItems} onPress={() => this.OnTabItemHandler('Telugu')}>Telugu</Text>
</View>
<View style = {styles.tabContainer}>
<TouchableOpacity style={styles.tabIcons} onPress={() => this.OnTabItemHandler(‘Tamil’)}>
<Image
style={styles.tabItemsImages}
source={this.state.flagImage === true ?
tamilActiveImage :
tamilDeActiveImage}
/>
</TouchableOpacity>
<Text style={styles.tabTextItems} onPress={() => this.OnTabItemHandler('Tamil')}> Tamil </Text>
</View>
<View style = {styles.tabContainer}>
<TouchableOpacity style={styles.tabIcons} onPress={() => this.OnTabItemHandler(‘Hindi’)}>
<Image
style={styles.tabItemsImages}
source={this.state.flagImage === true ?
hindiActiveImage :
hindiDeActiveImage}
/>
</TouchableOpacity>
<Text style={styles.tabTextItems} onPress={() => this.OnTabItemHandler('Hindi')}> Hindi </Text>
</View>
<View style = {styles.tabContainer}>
<TouchableOpacity style={styles.tabIcons} onPress={() => this.OnTabItemHandler(‘English’)}>
<Image
style={styles.tabItemsImages}
source={this.state.flagImage === true ?
englishActiveImage :
englishDeActiveImage}
/>
</TouchableOpacity>
<Text style={styles.tabTextItems} onPress={() => this.OnTabItemHandler('English')}> English </Text>
</View>
</View>
{this.renderBottomContent(item)}
</View>
);
}
Can anyone suggest me, Where I am doing wrong?
And in the method renderBottomContent(), these flagForTelugu,
flagForTamil, flagForHindi, flagForEnglish showing as undefined while
debugging time.
I'm not good to explaining how the code works.
but the idea is you need 1 state called selectedIndex and the rest is you need to check the active image with the selectedIndex is match show the active image
the example code may looks like this:
import React, { Component } from 'react';
import RN from 'react-native';
export default class App extends Component {
constructor(props) {
super(props);
this.state={
selectedIndex:0,
//you can change every urlActive and urlInactive url to your needed image
tabList:[
{label:'tab 1', urlActive:'https://livelovely.com/static/images/full-listing/icon-modal-success%402x.png', urlInactive:'https://icon2.kisspng.com/20180823/ioc/kisspng-traffic-sign-image-traffic-code-no-symbol-inactive-symbol-www-pixshark-com-images-gallerie-5b7e884790b8a3.5710860815350190795928.jpg'},
{label:'tab 2', urlActive:'https://livelovely.com/static/images/full-listing/icon-modal-success%402x.png', urlInactive:'https://icon2.kisspng.com/20180823/ioc/kisspng-traffic-sign-image-traffic-code-no-symbol-inactive-symbol-www-pixshark-com-images-gallerie-5b7e884790b8a3.5710860815350190795928.jpg'},
{label:'tab 3', urlActive:'https://livelovely.com/static/images/full-listing/icon-modal-success%402x.png', urlInactive:'https://icon2.kisspng.com/20180823/ioc/kisspng-traffic-sign-image-traffic-code-no-symbol-inactive-symbol-www-pixshark-com-images-gallerie-5b7e884790b8a3.5710860815350190795928.jpg'},
]
}
}
render() {
console.disableYellowBox = true;
return (
<RN.View style={{flex:1}}>
//creating the tab height
<RN.View style={{flex:0.07, flexDirection:'row'}}>
{
//loop throught the state
this.state.tabList.map((item,index)=>{
return(
//the style just to make it beautiful and easy to debug
<RN.TouchableOpacity style={{flex:1, alignItems:'center', backgroundColor:index==0?'green':index==1?'blue':'yellow'}}
//this onpress to handle of active selected tab
onPress={()=>{this.setState({selectedIndex:index})}}
>
<RN.View>
<RN.Text>{item.label}</RN.Text>
<RN.Image
//here's the magic show off
source={{uri:this.state.selectedIndex==index?item.urlActive:item.urlInactive}}
style={{width:20, height:20, resizeMode:'contain'}}
/>
</RN.View>
</RN.TouchableOpacity>
)
})
}
</RN.View>
</RN.View>
);
}
}
and the result look like :