For Form Validation, Instead of using a package I tried to build one myself. So No matter how many fields you have, the validation gets added automatically. But there is one MINOR issue.
Since the set state is async, I'm only able to get the last typed value after typing one more lettter.
For Example : If I need to show an error "Password must contain atleast 6 characters" , This error gets displayed. But it only goes away if you type the 7th character. Same with other fields aswell.
I am checking the validation on the onChangeText and onBlur , I also tried with onKeyPress.
Any solution is apreciated.
Here is the code: I have removed the styles etc. So this code should work for you out of the box.
import React, { useState, useRef } from 'react';
import { Text, View, TextInput } from 'react-native';
const Signup = ({}) => {
const inputRef = useRef([]);
const [inputs, setInputs] = useState([
{ id: 0, placeholder: 'First Name', name: 'firstName', type: 'text', hasError: false, errMessage: '' },
{ id: 1, placeholder: 'Last Name', name: 'lastName', type: 'text', hasError: false, errMessage: '' },
{ id: 2, placeholder: 'Email', name: 'email', type: 'email', hasError: false, errMessage: '' },
{ id: 3, placeholder: 'Password', name: 'password', type: 'password', mhasError: false, errMessage: '' },
{
id: 4,
placeholder: 'Confirm Password',
name: 'confirmPassword',
type: 'password',
hasError: false,
errMessage: '',
},
]);
const [fields, setFields] = useState({
firstName: '',
lastName: '',
email: '',
password: '',
confirmPassword: '',
});
const handleChange = (text, fieldName, id, type) => {
setFields(currentValue => ({
...currentValue,
[fieldName]: text,
}));
validateForm(fieldName, id, type);
};
const validateForm = (fieldName, id, type) => {
const ID = id;
const newInput = [...inputs];
if (type === 'text') {
if (fields[fieldName].length === 0 || fields[fieldName] === '') {
newInput[ID].errMessage = 'Please fill the field';
newInput[ID].hasError = true;
} else if (fields[fieldName].length < 3) {
newInput[ID].hasError = true;
newInput[ID].errMessage = 'Must be more than 2 letters';
} else {
newInput[ID].errMessage = '';
newInput[ID].hasError = false;
}
}
if (type === 'email') {
if (fields[fieldName].length === 0 || fields[fieldName] === '') {
newInput[ID].errMessage = 'Please fill the field';
newInput[ID].hasError = true;
} else if (
!fields[fieldName].match(
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
)
) {
newInput[ID].hasError = true;
newInput[ID].errMessage = 'Invalid Email';
} else {
newInput[ID].errMessage = '';
newInput[ID].hasError = false;
}
}
if (type === 'password' && fieldName === 'password') {
if (fields[fieldName].length === 0 || fields[fieldName] === '') {
newInput[ID].errMessage = 'Please fill the field';
newInput[ID].hasError = true;
} else if (fields[fieldName].length < 6) {
newInput[ID].hasError = true;
newInput[ID].errMessage = 'Your password must be at least 6 characters';
} else if (fields[fieldName].search(/[a-z]/i) < 0) {
newInput[ID].hasError = true;
newInput[ID].errMessage = 'Your password must contain at least one letter.';
} else if (fields[fieldName].search(/[0-9]/) < 0) {
newInput[ID].hasError = true;
newInput[ID].errMessage = 'Your password must contain at least one digit.';
} else {
newInput[ID].errMessage = '';
newInput[ID].hasError = false;
}
}
if (type === 'password' && fieldName === 'confirmPassword') {
if (fields['confirmPassword'] !== fields['password']) {
newInput[ID].errMessage = "Password doesn't match";
newInput[ID].hasError = true;
} else {
newInput[ID].errMessage = '';
newInput[ID].hasError = false;
}
}
setInputs(newInput);
};
return (
<View style={{ paddingTop: 90 }}>
<View>
{inputs &&
inputs.map((value, index) => (
<View key={index}>
<TextInput
onChangeText={text => {
handleChange(text, value.name, value.id, value.type);
}}
onBlur={() => validateForm(value.name, value.id, value.type)}
placeholder={value.placeholder}
ref={input => (inputRef.current[value.id] = input)}
/>
{value.hasError && <Text style={{ color: 'red', marginTop: 3 }}>{value.errMessage}</Text>}
</View>
))}
</View>
</View>
);
};
export default Signup;