Why does my keyboard get dismissed at each keystroke when I extract a View with a TextInput to a function, but not when I return it directly? - react-native

I created a FormInput component which encapsulates a View with a TextInput:
<FormInput inputType="text" title={translate("Exam Name")} value={name} setValue={setName} ref={examNameRef} required />
Inside FormInput I do the following:
if (inputType === 'text') {
// return (
// <View style={[styles.button, { height: 90 }]} >
// <View style={{ flexDirection: 'row' }}>
// <Text style={[styles.fieldLabel, {}]}>{title}</Text>
// {required && <Text style={{ color: 'red' }}>{' *'}</Text>}
// </View>
// <View>
// {requiredValidationError ?
// <Text style={[styles.fieldValue, { borderColor: 'red', color: 'red' }]}>{'Campo Obrigatório'}</Text>
// :
// <TextInput style={[styles.fieldValue]} value={value} onChangeText={setValue} />
// }
// </View>
// </View>
// )
return <InputText />
The function InputText has the same code as the commented code above:
function InputText() {
return (
<View style={[styles.button, { height: 90 }]} >
<View style={{ flexDirection: 'row' }}>
<Text style={[styles.fieldLabel, {}]}>{title}</Text>
{required && <Text style={{ color: 'red' }}>{' *'}</Text>}
</View>
<View>
{requiredValidationError ?
<Text style={[styles.fieldValue, { borderColor: 'red', color: 'red' }]}>{'Campo Obrigatório'}</Text>
:
<TextInput style={[styles.fieldValue]} value={value} onChangeText={setValue} />
}
</View>
</View>
)
}
When I use it like this my keyboard keeps getting dismissed at every key stroke,but when I uncomment the commented part above and return the View directly instead of putting it inside a function this bug doesn't happen. What could be the problem?
Here's the whoe FormInput.js:
import React, { useState, useEffect, useRef, forwardRef, useImperativeHandle } from 'react';
import { Text, Pressable, View, TextInput, SafeAreaView, TouchableOpacity, Platform, ActivityIndicator, StyleSheet, Switch } from 'react-native';
import { useNavigation, useRoute, useTheme } from '#react-navigation/native';
import { translate } from '../../translate';
import Page from '../../components/Page';
import Picker from '../../components/Picker';
import Modal from '../../components/Modal';
import Button from '../../components/Button';
import DateTimePicker from '#react-native-community/datetimepicker';
import Toast from 'react-native-simple-toast';
import moment from 'moment';
import Icon from 'react-native-vector-icons/Ionicons';
Icon.loadFont();
const FormInput = forwardRef(({ inputType, title, value, setValue, required, maxLength }, ref) => {
const [modalVisible, setModalVisible] = useState(false);
const [internalValue, setInternalValue] = useState(value);
const [dateTimePickerMode, setDateTimePickerMode] = useState("date");
const [date, setDate] = useState(new Date());
const [requiredValidationError, setRequiredValidationError] = useState(false);
const inputRef = useRef();
useImperativeHandle(ref, () => ({
validate() {
if (required) {
if (internalValue) {
setRequiredValidationError(false)
} else {
setRequiredValidationError(true)
}
}
},
error: requiredValidationError
}));
const onChangeDate = (event, newDate) => {
if (event.type === "dismissed") {
setDateTimePickerMode("date")
setModalVisible(false);
return;
}
const dateWithTime = new Date(date);
if (dateTimePickerMode === 'date') {
setModalVisible(true);
setDate(newDate || new Date());
setDateTimePickerMode('time');
} else {
setModalVisible(false);
dateWithTime.setHours(newDate.getHours());
dateWithTime.setMinutes(newDate.getMinutes());
setDateTimePickerMode('date');
setValue(dateWithTime);
}
}
function InputSwitch() {
return (
<View style={[styles.button, { paddingRight: 15 }]} >
<Text style={[styles.fieldLabel, { marginBottom: 10 }]}>{title}</Text>
<View style={{ marginRight: 30 }}>
<Switch
style={{ transform: [{ scaleX: Platform.select({ ios: 0.8, android: 1.3 }) }, { scaleY: Platform.select({ ios: 0.8, android: 1.3 }) }] }}
thumbColor={"#f4f3f4"}
onValueChange={setValue}
value={value}
/>
</View>
</View>
)
}
function InputText() {
return (
<View style={[styles.button, { height: 90 }]} >
<View style={{ flexDirection: 'row' }}>
<Text style={[styles.fieldLabel, {}]}>{title}</Text>
{required && <Text style={{ color: 'red' }}>{' *'}</Text>}
</View>
<View>
{requiredValidationError ?
<Text style={[styles.fieldValue, { borderColor: 'red', color: 'red' }]}>{'Campo Obrigatório'}</Text>
:
<TextInput style={[styles.fieldValue]} value={value} onChangeText={setValue} />
}
</View>
</View>
)
}
function InputNumber() {
return (
<View style={[styles.button, { height: 90 }]} >
<View style={{ flexDirection: 'row' }}>
<Text style={[styles.fieldLabel, {}]}>{title}</Text>
{required && <Text style={{ color: 'red' }}>{' *'}</Text>}
</View>
<View>
<Text style={[styles.fieldValue, { borderColor: requiredValidationError ? 'red' : 'grey', color: requiredValidationError ? 'red' : 'grey' }]}>{requiredValidationError ? 'Campo Obrigatório' : value}</Text>
</View>
</View>
)
}
function InputDate() {
return (
<View>
{inputType === 'date' && modalVisible && (
<DateTimePicker
testID="dateTimePicker"
value={internalValue ? new Date(internalValue) : new Date()}
is24Hour={true}
mode={dateTimePickerMode}
onChange={onChangeDate}
/>
)}
<Pressable style={[styles.button, { height: 90 }]} onPress={() => setModalVisible(true)} >
<View style={{ flexDirection: 'row' }}>
<Text style={[styles.fieldLabel, {}]}>{title}</Text>
{required && <Text style={{ color: 'red' }}>{' *'}</Text>}
</View>
<Text style={styles.fieldValue}>{value ? moment(value).format('DD/MM/yyyy HH:mm') : ''}</Text>
</Pressable>
</View>
)
}
if (inputType === 'text') {
// return (
// <View style={[styles.button, { height: 90 }]} >
// <View style={{ flexDirection: 'row' }}>
// <Text style={[styles.fieldLabel, {}]}>{title}</Text>
// {required && <Text style={{ color: 'red' }}>{' *'}</Text>}
// </View>
// <View>
// {requiredValidationError ?
// <Text style={[styles.fieldValue, { borderColor: 'red', color: 'red' }]}>{'Campo Obrigatório'}</Text>
// :
// <TextInput style={[styles.fieldValue]} value={value} onChangeText={setValue} />
// }
// </View>
// </View>
// )
return <InputText />
} else if (inputType === 'number') {
return <InputNumber />
} else if (inputType === 'switch') {
return <InputSwitch />
} else if (inputType === 'date') {
return <InputDate />
} else {
return <Text style={{ backgroundColor: 'orange', textAlign: 'center', padding: 10, margin: 10 }}>Input do tipo {inputType} não está implementado</Text>
}
})
const styles = StyleSheet.create({
container: {
backgroundColor: '#A7A6A6',
marginBottom: 100
},
header: {
backgroundColor: '#FF000010',
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: 16,
paddingVertical: Platform.select({ ios: 10, android: 10 })
},
title: {
flex: 1,
fontSize: 32,
color: '#626262',
fontWeight: 'bold',
backgroundColor: '#00FF0010',
},
modalView: {
marginVertical: 230,
marginHorizontal: 20,
backgroundColor: "white",
borderRadius: 20,
padding: 35,
alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5
},
button: {
padding: 5
},
fieldLabel: {
color: "grey",
fontWeight: "bold",
textAlign: "left"
},
fieldValue: {
color: "black",
textAlign: "right",
borderBottomWidth: 1,
paddingTop: 10,
paddingRight: 10,
paddingBottom: 5,
textAlign: 'right',
borderColor: 'grey',
},
modalText: {
marginBottom: 15,
textAlign: "center"
},
textInput: {
borderWidth: 0,
paddingHorizontal: 20,
fontSize: 16,
marginBottom: 4,
color: '#626262',
borderRadius: 0,
borderBottomWidth: 1,
borderColor: '#626262',
width: 300,
textAlign: 'center'
},
});
export default FormInput;
And the return of the parent component:
return (
<>
<Page type="static" title={'Avaliação'} subtitle={'Editar'}>
<ScrollView style={{ flexGrow: 0.8, paddingHorizontal: 5}} keyboardShouldPersistTaps="always">
<FormInput inputType="text" title={translate("Exam Name")} value={name} setValue={setName} ref={examNameRef} required />
<FormInput inputType="text" title={translate("Code")} value={code} setValue={setCode} maxLength={8} ref={examCodeRef} required />
<FormInput inputType="number" title={translate("Max Grade")} value={maxGrade} setValue={setMaxGrade} />
<FormInput inputType="number" title={translate("Weight")} value={weight} setValue={setWeight} ref={examWeightRef} required />
<FormInput inputType="date" title={translate("Start Date")} value={startDate} setValue={setStartDate} />
<FormInput inputType="date" title={translate("End Date")} value={endDate} setValue={setEndDate} />
<FormInput inputType="switch" title={translate("Ignore Formula")} value={ignoreFormula} setValue={setIgnoreFormula} />
</ScrollView>
</Page>
<View style={{}}>
<Button style={[styles.button, {}]} textStyle={styles.buttonText} title={translate('Save')} onPress={() => saveExam()} requestFeedback />
</View>
</>
);

Related

How to scroll To next item on a button click using FlatList in React Native?

I have an array of months which I am using to display months using a horizontal FlatList. I want the months to change using 2 buttons that are forward button to change the month in increasing order i.e from January to February and so on and a back button to change the month backwards i.e from January to December.
How can I make the buttons do so. Below monthName is an array that contains all the month names.
<ScrollView style={{flexGrow: 1}}>
<View style={{flex: 1, backgroundColor: '#fff', height: hp('130')}}>
<View
style={{
justifyContent: 'space-evenly',
width: wp('48'),
}}>
<FlatList
data={monthName}
pagingEnabled={true}
showsHorizontalScrollIndicator={false}
renderItem={(month, index) => (
<View>
<Months
showMonth={month.item}
id={month.id}
refer={flatRef}
/>
</View>
)}
keyExtractor={(item, index) => item.id.toString()}
horizontal
// snapToInterval={Dimensions.get('window').width}
snapToAlignment={'center'}
ref={(node) => (flatRef = node)}
/>
</View>
<View
style={{
justifyContent: 'space-evenly',
width: wp('12'),
}}>
{/* {} */}
<IonIcons.Button --> the button that makes the month increment.
name="arrow-forward"
size={25}
backgroundColor="white"
color="black"
// onPress={() => console.log('pressed')}
onPress={() => {
flatRef.scrollToIndex({index: ?});
}}
/>
</View>
</View>
</ScrollView>
try to access ref using current and it should work
this.flatRef.current.scrollToIndex({index: monthName.length > this.state.currentindex ? this.state.currentindex++ : this.state.currentindex });
import React, { useRef } from 'react';
import {
FlatList,
StyleSheet,
Text,
TouchableOpacity,
View
} from 'react-native';
import { wp } from '../../constants/scaling';
import { colors } from '../../constants/theme';
import bookingprocess from '../../data/BookingProcess';
import { textStyles } from '../../styles/textStyles';
import { RFValue } from 'react-native-responsive-fontsize';
import AntDesign from 'react-native-vector-icons/AntDesign';
const BookingProcess = ({}) => {
const flatListRef = useRef(FlatList);
const nextPress = index => {
if (index <= 2) {
flatListRef?.current?.scrollToIndex({
animated: true,
index: index + 1
});
}
};
const backPress = index => {
if (index >= 1) {
flatListRef?.current?.scrollToIndex({
animated: true,
index: index - 1
});
}
};
return (
<View
style={{
...styles.cardView,
padding: 0,
elevation: 0,
borderWidth: 1,
borderColor: '#f2f2f2',
overflow: 'hidden'
}}>
<View
style={{
padding: wp(2),
backgroundColor: colors.primaryColor
}}>
<Text
style={{
...textStyles.heading,
color: '#fff'
}}>
Booking Process
</Text>
</View>
<Text
style={{
...textStyles.mediumheading,
padding: wp(2),
paddingBottom: 0
}}>
You can reserve your parking slot in advance. Please follow
these four simple steps to book your parking slot.
</Text>
<FlatList
data={bookingprocess}
horizontal={true}
ref={flatListRef}
contentContainerStyle={{ padding: wp(2) }}
showsHorizontalScrollIndicator={false}
keyExtractor={(item, index) => item.id}
renderItem={({ item, index }) => {
return (
<View style={styles.innerCard}>
{item.image}
<View style={styles.ButtonBox}>
<TouchableOpacity
onPress={() => backPress(index)}
style={{
backgroundColor: colors.secondaryColor,
borderRadius: wp(50)
}}>
<AntDesign
name="leftcircle"
size={RFValue(25)}
color={colors.primaryColor}
/>
</TouchableOpacity>
<TouchableOpacity
onPress={() => nextPress(index)}
style={{
backgroundColor: colors.secondaryColor,
borderRadius: wp(50)
}}>
<AntDesign
name="rightcircle"
size={RFValue(25)}
color={colors.primaryColor}
/>
</TouchableOpacity>
</View>
<View style={styles.innercardHeaderView}>
<Text style={styles.headingTextNumber}>
{item.id}. {item.title}
</Text>
</View>
<Text style={styles.description}>
{item.description}
</Text>
</View>
);
}}
/>
</View>
);
};
export default BookingProcess;
const styles = StyleSheet.create({
cardView: {
backgroundColor: colors.white,
margin: wp(2),
elevation: 4,
borderRadius: wp(2),
padding: wp(2),
width: wp(94)
},
innerCard: {
margin: wp(2),
borderRadius: wp(2),
padding: wp(0),
paddingTop: 0,
paddingHorizontal: 0,
overflow: 'hidden',
width: wp(90),
elevation: 5,
marginLeft: 0,
padding: wp(2),
backgroundColor: '#fff'
},
ButtonBox: {
position: 'absolute',
flexDirection: 'row',
right: 0,
justifyContent: 'space-between',
width: wp(20),
padding: wp(2)
},
innercardHeaderView: {
backgroundColor: '#0000',
flexDirection: 'row',
padding: wp(2),
paddingBottom: 0,
alignItems: 'center'
},
headingTextNumber: {
...textStyles.heading,
color: colors.primaryColor,
textAlign: 'center',
alignSelf: 'center',
textAlignVertical: 'center'
},
description: {
...textStyles.mediumheading,
paddingHorizontal: wp(2),
textAlign: 'justify'
}
});
Instead of using a FlatList I would suggest you to make a state variable and execute it like this
Working example - Here
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { AntDesign } from '#expo/vector-icons';
...
const [SelectMonth, SetSelectMonth] = React.useState(monthName[0]);
const NextPress = () => {
if (SelectMonth.id !== 12) {
let temp = monthName.find((c) => c.id === SelectMonth.id + 1);
if (temp) {
SetSelectMonth(temp);
}
}
};
const PrevPress = () => {
if (SelectMonth.id !== 1) {
let temp = monthName.find((c) => c.id === SelectMonth.id - 1);
if (temp) {
SetSelectMonth(temp);
}
}
};
return (
<View style={styles.container}>
<View style={styles.CalenderBox}>
<AntDesign
name="caretleft"
size={30}
color="black"
onPress={() => PrevPress()}
/>
<View style={styles.MonthNameBox}>
<Text style={{ fontWeight: 'bold', fontSize: 24 }}>
{SelectMonth.name}
</Text>
</View>
<AntDesign
name="caretright"
size={30}
color="black"
onPress={() => NextPress()}
/>
</View>
</View>
);

Adding ImageBackground to React Native Login Screen

I found this great code sample/layout -- see below -- for a React Native login screen. All I want to do is to have an ImageBackground as opposed to the current solid background.
When I add ImageBackground to the code, it throws everything off and instead of the image covering the entire screen, everything gets squished in the middle and all alingment gets out of whack. What am I doing wrong here?
Here's the original code with solid background:
import React from 'react';
import { StyleSheet, Text, View, TextInput, TouchableOpacity } from 'react-native';
export default class App extends React.Component {
state={
email:"",
password:""
}
render(){
return (
<View style={styles.container}>
<Text style={styles.logo}>HeyAPP</Text>
<View style={styles.inputView} >
<TextInput
style={styles.inputText}
placeholder="Email..."
placeholderTextColor="#003f5c"
onChangeText={text => this.setState({email:text})}/>
</View>
<View style={styles.inputView} >
<TextInput
secureTextEntry
style={styles.inputText}
placeholder="Password..."
placeholderTextColor="#003f5c"
onChangeText={text => this.setState({password:text})}/>
</View>
<TouchableOpacity>
<Text style={styles.forgot}>Forgot Password?</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.loginBtn}>
<Text style={styles.loginText}>LOGIN</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.loginText}>Signup</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#003f5c',
alignItems: 'center',
justifyContent: 'center',
},
logo:{
fontWeight:"bold",
fontSize:50,
color:"#fb5b5a",
marginBottom:40
},
inputView:{
width:"80%",
backgroundColor:"#465881",
borderRadius:25,
height:50,
marginBottom:20,
justifyContent:"center",
padding:20
},
inputText:{
height:50,
color:"white"
},
forgot:{
color:"white",
fontSize:11
},
loginBtn:{
width:"80%",
backgroundColor:"#fb5b5a",
borderRadius:25,
height:50,
alignItems:"center",
justifyContent:"center",
marginTop:40,
marginBottom:10
},
loginText:{
color:"white"
}
});
This produces this nice layout:
And I simply add an image background with the following code which doesn't work at all:
<View style={styles.container}>
<ImageBackground
source={require("../../assets/images/background/teton_snake_dimmed.jpg")}
style={styles.imageBackground}
>
<Text style={styles.logo}>HeyAPP</Text>
<View style={styles.inputView} >
<TextInput
style={styles.inputText}
placeholder="Email..."
placeholderTextColor="#003f5c"
onChangeText={text => this.setState({ email: text })} />
</View>
<View style={styles.inputView}>
<TextInput
secureTextEntry
style={styles.inputText}
placeholder="Password..."
placeholderTextColor="#003f5c"
onChangeText={text => this.setState({ password: text })} />
</View>
<TouchableOpacity>
<Text style={styles.forgot}>Forgot Password?</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.loginBtn}>
<Text style={styles.loginText}>LOGIN</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.loginText}>Signup</Text>
</TouchableOpacity>
</ImageBackground>
</View>
And here's the updated styles. The only thing I add is the imageBackground:
container: {
flex: 1,
backgroundColor: '#003f5c',
alignItems: 'center',
justifyContent: 'center',
},
logo: {
fontWeight: "bold",
fontSize: 50,
color: "#fb5b5a",
marginBottom: 40
},
imageBackground: {
flex: 1,
resizeMode: "cover"
},
inputView: {
width: "80%",
backgroundColor: "#465881",
borderRadius: 25,
height: 50,
marginBottom: 20,
justifyContent: "center",
padding: 20
},
inputText: {
backgroundColor: "#465881",
height: 50,
color: "white"
},
forgot: {
color: "white",
fontSize: 11
},
loginBtn: {
width: "80%",
backgroundColor: "#fb5b5a",
borderRadius: 25,
height: 50,
alignItems: "center",
justifyContent: "center",
marginTop: 40,
marginBottom: 10
},
loginText: {
color: "white"
}
});
What am I doing wrong here?
P.S. Here's the original code published by #Alhydra:
https://github.com/Alhydra/React-Native-Login-Screen-Tutorial/blob/master/App.js
Here is an example replace the image with the image you want
snack: https://snack.expo.io/#ashwith00/intelligent-banana
code:
import React from 'react';
import {
StyleSheet,
Text,
View,
TextInput,
TouchableOpacity,
Image,
} from 'react-native';
export default class App extends React.Component {
state = {
email: '',
password: '',
};
render() {
return (
<View style={styles.container}>
<Image
style={styles.image}
source={{
uri:
'https://media.gettyimages.com/videos/loopable-color-gradient-background-animation-video-id1182636595?s=640x640',
}}
/>
<View style={styles.subContainer}>
<Text style={styles.logo}>HeyAPP</Text>
<View style={styles.inputView}>
<TextInput
style={styles.inputText}
placeholder="Email..."
placeholderTextColor="#003f5c"
onChangeText={(text) => this.setState({ email: text })}
/>
</View>
<View style={styles.inputView}>
<TextInput
secureTextEntry
style={styles.inputText}
placeholder="Password..."
placeholderTextColor="#003f5c"
onChangeText={(text) => this.setState({ password: text })}
/>
</View>
<TouchableOpacity>
<Text style={styles.forgot}>Forgot Password?</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.loginBtn}>
<Text style={styles.loginText}>LOGIN</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.loginText}>Signup</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
image: {
flex: 1,
},
container: {
flex: 1,
backgroundColor: '#003f5c',
},
subContainer: {
...StyleSheet.absoluteFillObject,
alignItems: 'center',
justifyContent: 'center',
},
logo: {
fontWeight: 'bold',
fontSize: 50,
color: '#fb5b5a',
marginBottom: 40,
},
inputView: {
width: '80%',
backgroundColor: '#465881',
borderRadius: 25,
height: 50,
marginBottom: 20,
justifyContent: 'center',
padding: 20,
},
inputText: {
height: 50,
color: 'white',
},
forgot: {
color: 'white',
fontSize: 11,
},
loginBtn: {
width: '80%',
backgroundColor: '#fb5b5a',
borderRadius: 25,
height: 50,
alignItems: 'center',
justifyContent: 'center',
marginTop: 40,
marginBottom: 10,
},
loginText: {
color: 'white',
},
});

Emailvalidator (require("email-validator") stopped working

I am doing email validation in my Signup form and all of a sudden it doesn't work anymore. I didn't change the signup.js file so it is a bit strange. I started working on the login.js file today so maybe there is some 'interference', but I don't have any idea where to look fist to be honest.
So here is the signup.js, where I put the emailvalidation that doesn't work anymore in bold.
import React, { Component } from 'react';
import { Text, StyleSheet, TouchableOpacity, Image, TextInput, View } from 'react-native';
import firebase from 'react-native-firebase';
var validator = require("email-validator");
export default class loginComponent extends Component {
constructor(props) {
super(props);
this.state = {firstName: ''};
this.state = {lastName: ''};
this.state = {email: ''};
this.state = {password: ''};
this.state = {emailValidated: false};
this.state = {errorMessage: null};
}
handleSignUp = () => {
firebase
.auth()
.createUserWithEmailAndPassword(this.state.email, this.state.password)
.then(() => this.props.navigation.navigate('Main'))
.catch(error => this.setState({ errorMessage: error.message }))
}
render() {
function renderEmailValidationState(emailInput) {
if(validator.validate(emailInput)) {
return false;
} else {
return true;
}
}
return (
<View style={styles.container}>
<View style={styles.logoContainer} >
<Image source={require('./assets/logo.png')} style={styles.logo}></Image>
<Text style={styles.slush}>
Lenen of huren, {"\n"} bij de buren!
</Text>
</View>
<View style={styles.formContainer}>
<View style={styles.inputTextFieldContainer}>
{this.state.errorMessage &&
<Text style={{ color: 'red' }}>
{this.state.errorMessage}
</Text>
}
<TextInput
style={styles.inputTextField}
placeholder="Enter you first name"
value={this.state.text}
backgroundColor="white"
onChangeText={(firstName) => this.setState({firstName})}
/>
<TextInput
style={styles.inputTextField}
placeholder="Enter you last name"
value={this.state.text}
backgroundColor="white"
onChangeText={(lastName) => this.setState({lastName})}
/>
<TextInput
style={styles.inputTextField}
placeholder="Enter your e-mail"
value={this.state.text}
backgroundColor="white"
onChangeText={(email) => this.setState({email})}
/>
<TextInput
style={styles.inputTextField}
placeholder="Enter your password"
value={this.state.password}
backgroundColor="white"
onChangeText={(password) => this.setState({password})}
/>
<TouchableOpacity
disabled= {renderEmailValidationState(this.state.email)}
style={styles.buttonContainer}
onPress={this.handleSignUp}
>
<View>
<Text style={styles.buttonText}>Sign up!</Text>
</View>
</TouchableOpacity>
<Text style={styles.plainText}>
Already a user?
</Text>
<TouchableOpacity
style={styles.buttonContainer}
onPress={() => this.props.navigation.navigate('Login')}
>
<View>
<Text style={styles.buttonText}>Login!</Text>
</View>
</TouchableOpacity>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 2,
padding:10,
backgroundColor:'#c6f1e7',
alignItems: 'stretch',
justifyContent: 'space-around'
},
logoContainer: {
padding: 10,
height: 250,
justifyContent: 'center' ,
alignItems: 'center'
},
logo: {
width: 250,
height: 250
},
slush: {
fontSize: 20,
color: '#59616e',
fontFamily: 'Raleway-Regular'
},
formContainer: {
flex:1,
padding: 10,
},
inputTextFieldContainer: {
padding: 100,
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 30
},
inputTextField: {
padding: 10,
height: 40,
width: 300,
marginBottom: 10,
fontSize: 16,
fontFamily: 'Raleway-Regular',
},
buttonContainer: {
padding: 10,
marginBottom: 20,
width: 300,
alignItems: 'center',
backgroundColor: '#acdcd7',
},
buttonText: {
padding: 1,
fontSize: 16,
color: '#59616e',
fontFamily: 'Raleway-Regular',
},
plainText: {
padding: 1,
fontSize: 16,
marginBottom: 5,
fontFamily: 'Raleway-Regular',
color: '#59616e'
},
});
And this is the login.js, but that is work in progress.
import React, { Component } from 'react';
import { Text, StyleSheet, TouchableOpacity, Image, TextInput, View } from 'react-native';
import firebase from 'react-native-firebase';
var validator = require("email-validator");
export default class loginComponent extends Component {
constructor(props) {
super(props);
this.state = {email: ''};
this.state = {password: ''};
this.state = {emailValidated: false};
this.state = {errorMessage: null};
}
render() {
function renderEmailValidationState(emailInput) {
if(validator.validate(emailInput)) {
return false;
} else {
return true;
}
}
return (
<View style={styles.container}>
<View style={styles.logoContainer}>
<Image source={require('./assets/logo.png')} style={styles.logo}></Image>
<Text style={styles.slush}>
Huren bij de buren!
</Text>
</View>
<View style={styles.formContainer}>
<View style={styles.inputTextFieldContainer}>
{this.state.errorMessage &&
<Text style={{ color: 'red' }}>
{this.state.errorMessage}
</Text>
}
<TextInput
style={styles.inputTextField}
placeholder="Enter your e-mail"
value={this.state.text}
backgroundColor="white"
onChangeText={(email) => this.setState({email})}
/>
<TextInput
style={styles.inputTextField}
placeholder="Enter your password"
value={this.state.password}
backgroundColor="white"
onChangeText={(password) => this.setState({password})}
/>
<TouchableOpacity
**disabled= {renderEmailValidationState(this.state.email)}**
style={styles.buttonContainer}
onPress={this.handleSignUp}
>
<View>
<Text style={styles.buttonText}>Sign up!</Text>
</View>
</TouchableOpacity>
<Text style={styles.plainText}>
Don't have an account?
</Text>
<TouchableOpacity
style={styles.buttonContainer}
onPress={() => this.props.navigation.navigate('SignUp')}
>
<View>
<Text style={styles.buttonText}>Register!</Text>
</View>
</TouchableOpacity>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 2,
padding:10,
backgroundColor:'#c6f1e7',
alignItems: 'stretch',
justifyContent: 'space-around'
},
logoContainer: {
padding: 10,
height: 350,
justifyContent: 'center' ,
alignItems: 'center'
},
logo: {
width: 250,
height: 250
},
slush: {
fontSize: 25,
color: '#59616e',
fontFamily: 'Raleway-Regular'
},
formContainer: {
flex:1,
padding: 10,
},
inputTextFieldContainer: {
padding: 100,
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 30
},
inputTextField: {
padding: 10,
height: 40,
width: 300,
marginBottom: 10,
fontSize: 16,
fontFamily: 'Raleway-Regular',
},
buttonContainer: {
padding: 10,
marginBottom: 20,
width: 300,
alignItems: 'center',
backgroundColor: '#acdcd7',
},
buttonText: {
padding: 1,
fontSize: 16,
color: '#59616e',
fontFamily: 'Raleway-Regular',
},
plainText: {
padding: 1,
fontSize: 16,
marginBottom: 5,
fontFamily: 'Raleway-Regular',
color: '#59616e'
},
});
Can anyone point me in the good direction?
Thanks a lot!
Tim
try this npm i raysk-vali
instead of email-validator.
usage:
const { isEmail } = require("raysk-vali");
isEmail("abc#example.com") // return true
isEmail("abcexample.com") // return false
for more checkout the documentation : https://www.npmjs.com/package/raysk-vali.

How to create dynamic checkbox in react native

I am able to create the dynamic checkbox but i need to check and uncheck it separately, right now if i check one everything gets checked and if i uncheck everything gets unchecked.
How to change the value of checkbox separately for each checkbox from state?
import React from 'react';
import {View,Text,StyleSheet,TouchableOpacity,Image,Switch,Platform,Dimensions,PixelRatio,} from'react-native';
import ImagePicker from 'react-native-image-picker';
import { Input, Button } from 'react-native-elements';
import { moderateScale } from 'react-native-size-matters';
const deviceWidth = Dimensions.get('window').width;
const deviceHeight = Dimensions.get('window').height;
const calcHeight = x => PixelRatio.roundToNearestPixel((deviceHeight * x) / 100);
const calcWidth = x => PixelRatio.roundToNearestPixel((deviceWidth * x) / 100);
class ErrorScreen extends React.Component {
constructor() {
super();
this.state = {
arr: [],
parkPay: false,
itemChecked: false,
index: null,
};
}
functionTwo = () => {
alert('func 2');
this.setState(() => ({
parkPay: true,
}));
};
checkedItem = index => {
console.log('this is index', index);
// let itemChecked = this.state.itemChecked
if (this.state.index != index) {
this.setState(() => ({
index: index,
itemChecked: !this.state.itemChecked,
}));
}
};
addParkField = () => {
console.log('jjjjj');
console.log(' ^^ props in parking form ^^ ', this.props);
let x = 0;
this.setState(() => ({
arr: [...this.state.arr, ''],
}));
// this.addFieldSecond()
// this.props.addParkFieldSecond()
};
render() {
return (
<View>
<View
style={{flex: 1, paddingRight: calcWidth(4),paddingLeft: calcWidth(6), paddingTop: calcHeight(4),paddingBottom: calcHeight(4),
}}>
<Input
placeholder="Enter Amount"
label="Enter Amount"
labelStyle={{ fontWeight: '200', color: 'black' }}
inputContainerStyle={{
paddingRight: calcWidth(2),
paddingLeft: calcWidth(2),
paddingTop: calcHeight(1),
paddingBottom: calcHeight(1),
}}
// onChangeText={this.props.parkingAmount}
/>
<Text style={[styles.error]}>{this.state.errors.Amount}</Text>
<View
style={{ paddingLeft: calcWidth(2), paddingTop: calcHeight(4) }}>
<View style={{ paddingRight: calcWidth(70) }}>
<Switch
value={this.state.parkPay}
style={
Platform.OS === 'ios' ? styles.switchIOS : styles.switchAND
}
// onValueChange={(value) => {this.props.toggleCustomerParkingPay(value); this.functionTwo()}}
/>
</View>
<Text style={{ paddingTop: calcHeight(8) }}>Paid By Customer</Text>
</View>
</View>
<View style={{}}>
{this.state.arr.map((extra, index) => {
return (
<View
style={{
flex: 1,
paddingRight: calcWidth(4),
paddingLeft: calcWidth(20),
paddingTop: calcHeight(15),
paddingBottom: calcHeight(4),
}}
key={index}>
<Input
placeholder="Enter Amount"
label="Enter Amount"
labelStyle={{ fontWeight: '200', color: 'black' }}
inputContainerStyle={{
paddingRight: calcWidth(2),
paddingLeft: calcWidth(2),
paddingTop: calcHeight(1),
paddingBottom: calcHeight(1),
}}
// onChangeText={this.handleAmount}
// onChangeText={this.props.parkingAmount}
/>
<Text style={[styles.error]}>{this.state.errors.Amount}</Text>
<View style={{ paddingTop: calcHeight(4) }}>
<View style={{ paddingRight: calcWidth(70) }}>
<Switch
value={this.state.parkPay}
style={
Platform.OS === 'ios'
? styles.switchIOS
: styles.switchAND
}
// onValueChange={(value) => {this.props.toggleCustomerParkingPay(value);}}
/>
</View>
<Text style={{ paddingTop: calcHeight(8) }}>
Paid By Customer
</Text>
</View>
</View>
);
})}
<View>
<View
style={{ paddingLeft: calcWidth(60), paddingTop: calcHeight(2) }}>
<TouchableOpacity
style={[styles.cardCirclePassenger]}
onPress={this.addParkField}>
<View
style={{
justifyContent: 'center',
alignItems: 'center',
paddingTop: calcHeight(2.2),
}}>
{/* <Image
style={{width: 24, height: 24}}
source={require('../../images/Group424.png')}
/> */}
<Text>Add</Text>
</View>
</TouchableOpacity>
</View>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
cardCirclePassenger: {
backgroundColor: '#31588A',
marginBottom: 10,
marginLeft: '5%',
width: 60,
height: 60,
borderRadius: 60 / 2,
borderColor: 'white',
shadowOpacity: 0.2,
shadowRadius: 1,
shadowOffset: {
width: 3,
height: 3,
},
borderWidth: 1,
},
switchIOS: {
transform: [
{ scaleX: moderateScale(0.7, 0.2) },
{ scaleY: moderateScale(0.7, 0.2) },
],
},
switchAND: {
transform: [
{ scaleX: moderateScale(1, 0.2) },
{ scaleY: moderateScale(1, 0.2) },
],
},
});
export default ErrorScreen;
i worked around a little bit and found the below way to generate dynamic checboxes along with separate state values. hope this helps someone.
The below code creates dynamic key-value pairs in state. if you console.log the state in your render you'll see (check0:true check1:true check2: false ....) .
<Switch
value={this.state[`check${key}`]}
onValueChange={value => this.setState({ [`check${key}`]: value })}
/>

Invariant Violation: Element type is invalid: expected a string or a class/function but got: undefined.

Developers,
HELP. I'm getting this error with the below, I've been pouring over it trying to find the issue but just can't see it! What's wrong here? It seems to be stemming from the code from 146 to 236.
Invariant Violation: Element type is invalid: expected a string (for built-in >components) or a class/function (for composite components) but got: >undefined. You likely forgot to export your component from the file it's >defined in, or you might have mixed up default and named imports.
import React, { Component } from "react";
import PropTypes from "prop-types";
import {
View,
Text,
StyleSheet,
KeyboardAvoidingView,
LayoutAnimation,
UIManager,
Dimensions
} from "react-native";
import { Button, Input } from "react-native-elements";
import Icon from "react-native-vector-icons/FontAwesome";
import SimpleIcon from "react-native-vector-icons/SimpleLineIcons";
const SCREEN_WIDTH = Dimensions.get("window").width;
// Enable LayoutAnimation on Android
UIManager.setLayoutAnimationEnabledExperimental &&
UIManager.setLayoutAnimationEnabledExperimental(true);
const TabSelector = ({ selected }) => {
return (
<View style={styles.selectorContainer}>
<View style={selected && styles.selected} />
</View>
);
};
TabSelector.propTypes = {
selected: PropTypes.bool.isRequired
};
export default class AuthScreen extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
selectedCategory: 0,
isLoading: false,
isPasswordValid: true,
isConfirmationValid: true
};
this.selectCategory = this.selectCategory.bind(this);
this.login = this.login.bind(this);
this.signUp = this.signUp.bind(this);
}
selectCategory(selectedCategory) {
LayoutAnimation.easeInEaseOut();
this.setState({
selectedCategory,
isLoading: false
});
}
login() {
const { password } = this.state;
this.setState({ isLoading: true });
// Simulate an API call
setTimeout(() => {
LayoutAnimation.easeInEaseOut();
this.setState({
isLoading: false,
isPasswordValid: password.length >= 8 || this.passwordInput.shake()
});
}, 1500);
}
signUp() {
const { password, passwordConfirmation } = this.state;
this.setState({ isLoading: true });
// Simulate an API call
setTimeout(() => {
LayoutAnimation.easeInEaseOut();
this.setState({
isLoading: false,
isPasswordValid: password.length >= 8 || this.passwordInput.shake(),
isConfirmationValid:
password == passwordConfirmation || this.confirmationInput.shake()
});
}, 1500);
}
render() {
const {
selectedCategory,
isLoading,
isPasswordValid,
isConfirmationValid,
email,
password,
passwordConfirmation
} = this.state;
const isLoginPage = selectedCategory === 0;
const isSignUpPage = selectedCategory === 1;
return (
<View style={styles.container}>
<KeyboardAvoidingView
contentContainerStyle={styles.loginContainer}
behavior="position"
>
<View style={styles.titleContainer}>
<View style={{ flexDirection: "row" }}>
<Text style={styles.titleText}>BEAUX</Text>
</View>
<View style={{ marginTop: -10, marginLeft: 10 }}>
<Text style={styles.titleText}>VOYAGES</Text>
</View>
</View>
<View style={{ flexDirection: "row" }}>
<Button
disabled={isLoading}
clear
activeOpacity={0.7}
onPress={() => this.selectCategory(0)}
containerStyle={{ flex: 1 }}
titleStyle={[
styles.categoryText,
isLoginPage && styles.selectedCategoryText
]}
title={"Login"}
/>
<Button
disabled={isLoading}
clear
activeOpacity={0.7}
onPress={() => this.selectCategory(1)}
containerStyle={{ flex: 1 }}
titleStyle={[
styles.categoryText,
isSignUpPage && styles.selectedCategoryText
]}
title={"Sign up"}
/>
</View>
<View style={styles.rowSelector}>
<TabSelector selected={isLoginPage} />
<TabSelector selected={isSignUpPage} />
</View>
{/* //!ISSUE LIES HERE */}
<View style={styles.formContainer}>
<Input
leftIcon={
<Icon
name="envelope-o"
color="rgba(0, 0, 0, 0.38)"
size={25}
style={{ backgroundColor: "transparent" }}
/>
}
value={email}
keyboardAppearance="light"
autoFocus={false}
autoCapitalize="none"
autoCorrect={false}
keyboardType="email-address"
returnKeyType="next"
inputStyle={{ marginLeft: 10 }}
placeholder={"Email"}
containerStyle={{
borderBottomColor: "rgba(0, 0, 0, 0.38)"
}}
ref={input => (this.emailInput = input)}
onSubmitEditing={() => this.passwordInput.focus()}
onChangeText={email => this.setState({ email })}
/>
<Input
leftIcon={
<SimpleIcon
name="lock"
color="rgba(0, 0, 0, 0.38)"
size={25}
style={{ backgroundColor: "transparent" }}
/>
}
value={password}
keyboardAppearance="light"
autoCapitalize="none"
autoCorrect={false}
secureTextEntry={true}
returnKeyType={isSignUpPage ? "next" : "done"}
blurOnSubmit={true}
containerStyle={{
marginTop: 16,
borderBottomColor: "rgba(0, 0, 0, 0.38)"
}}
inputStyle={{ marginLeft: 10 }}
placeholder={"Password"}
ref={input => (this.passwordInput = input)}
onSubmitEditing={() =>
isSignUpPage ? this.confirmationInput.focus() : this.login()
}
onChangeText={password => this.setState({ password })}
errorMessage={
isPasswordValid ? null : "Please enter at least 8 characters"
}
/>
{isSignUpPage && (
<Input
icon={
<SimpleIcon
name="lock"
color="rgba(0, 0, 0, 0.38)"
size={25}
style={{ backgroundColor: "transparent" }}
/>
}
value={passwordConfirmation}
secureTextEntry={true}
keyboardAppearance="light"
autoCapitalize="none"
autoCorrect={false}
keyboardType="default"
returnKeyType={"done"}
blurOnSubmit={true}
containerStyle={{
marginTop: 16,
borderBottomColor: "rgba(0, 0, 0, 0.38)"
}}
inputStyle={{ marginLeft: 10 }}
placeholder={"Confirm password"}
ref={input => (this.confirmationInput = input)}
onSubmitEditing={this.signUp}
onChangeText={passwordConfirmation =>
this.setState({ passwordConfirmation })
}
errorMessage={
isConfirmationValid ? null : "Please enter the same password"
}
/>
)}
{/* //!ISSUE ENDS HERE */}
<Button
buttonStyle={styles.loginButton}
containerStyle={{ marginTop: 32, flex: 0 }}
activeOpacity={0.8}
title={isLoginPage ? "LOGIN" : "SIGN UP"}
onPress={isLoginPage ? this.login : this.signUp}
titleStyle={styles.loginTextButton}
loading={isLoading}
disabled={isLoading}
/>
</View>
</KeyboardAvoidingView>
<View style={styles.helpContainer}>
<Button
title={"Need help ?"}
titleStyle={{ color: "red" }}
buttonStyle={{ backgroundColor: "transparent" }}
underlayColor="transparent"
onPress={() => console.log("Account created")}
/>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: "#034d84",
flex: 1
},
rowSelector: {
height: 20,
flexDirection: "row",
alignItems: "center"
},
selectorContainer: {
flex: 1,
alignItems: "center"
},
selected: {
position: "absolute",
borderRadius: 50,
height: 0,
width: 0,
top: -5,
borderRightWidth: 70,
borderBottomWidth: 70,
borderColor: "white",
backgroundColor: "white"
},
loginContainer: {
alignItems: "center",
justifyContent: "center"
},
loginTextButton: {
fontSize: 16,
color: "white",
fontWeight: "bold"
},
loginButton: {
backgroundColor: "rgba(232, 147, 142, 1)",
borderRadius: 10,
height: 50,
width: 200
},
titleContainer: {
height: 150,
backgroundColor: "transparent",
justifyContent: "center"
},
formContainer: {
backgroundColor: "white",
width: SCREEN_WIDTH - 30,
borderRadius: 10,
paddingTop: 32,
paddingBottom: 32,
alignItems: "center"
},
loginText: {
fontSize: 16,
fontWeight: "bold",
color: "white"
},
categoryText: {
textAlign: "center",
color: "white",
fontSize: 24,
fontFamily: "light",
backgroundColor: "transparent",
opacity: 0.54
},
selectedCategoryText: {
opacity: 1
},
titleText: {
color: "white",
fontSize: 30,
fontFamily: "regular"
},
helpContainer: {
height: 64,
alignItems: "center",
justifyContent: "center"
}
});
Based on your input that you are on react-native-elements version 0.19.1, it seems the Input component isn't available (see docs). Only the v1.0.0 beta versions support Input as component.