I’m working on a login screen in a React Native application using react-hook-form
and yup
for form validation. I’ve implemented a feature that allows users to choose the sign-up method either by email or phone number.
The problem I’m encountering is that validation error messages for the email or phone number fields are not displayed when the form is submitted empty or when the input does not meet the validation rules. Only the password field’s error message is shown.
enter image description here
enter image description here
.......
const [signUpMethod, setSignUpMethod] = useState("phoneNumber");
const schema = yup.object().shape({
email: yup.string().when("signUpMethod", {
is: "email",
then: yup
.string()
.required("You should enter an email")
.email("Invalid email"),
}),
phoneNumber: yup.string().when("signUpMethod", {
is: "phoneNumber",
then: yup
.string()
.required("You should enter a phone number")
.matches(
/^((+[1-9]{1,4}[ -]*)|(([0-9]{2,3})[ -]*)|([0-9]{2,4})[ -]*)*?[0-9]{3,4}?[ -]*[0-9]{3,4}?$/,
"Phone number is not valid"
),
}),
password: yup.string().required("You should enter a password"),
});
const {
control,
handleSubmit,
formState: { errors },
} = useForm({
resolver: yupResolver(schema),
defaultValues: {
email: "",
password: "",
phoneNumber: "",
},
});
const onPressSend = async (formData) => {
console.log("???? ~ onPressSend ~ formData:", formData);
const { email, phoneNumber, password } = formData;
const number = "+" + countryCode + phoneNumber;
const loginData =
signUpMethod === "email"
? { username: email, password }
: { username: number, password };
console.log("???? ~ onPressSend ~ loginData:", loginData);
try {
dispatch(loginRequest());
login({ variables: loginData }).then((res) => {
dispatch(loginSuccess(res.data.login));
console.log("???? ~ login ~ res:", res);
});
console.log("???? ~ login ~ res.data.login:", res.data.login);
} catch (error) {
dispatch(loginFailure(error.message));
setErrorMessage(error.message);
console.log("====>", error);
}
};
...
return (
...
<View style={styles.singUpMethod}>
<TouchableOpacity
style={
signUpMethod === "email"
? styles.selectedMethod
: styles.notSelectedMethod
}
onPress={() => {
setSignUpMethod("email");
}}
>
<Text
style={
signUpMethod === "email"
? styles.selectedMethodText
: styles.notSelectedMethodText
}
>
Email
</Text>
</TouchableOpacity>
<TouchableOpacity
style={
signUpMethod === "phoneNumber"
? styles.selectedMethod
: styles.notSelectedMethod
}
onPress={() => {
setSignUpMethod("phoneNumber");
}}
>
<Text
style={
signUpMethod === "phoneNumber"
? styles.selectedMethodText
: styles.notSelectedMethodText
}
>
Phone
</Text>
</TouchableOpacity>
</View>
{signUpMethod === "email" && (
<Controller
control={control}
rules={{ required: true }}
render={({ field: { onChange, value, onBlur } }) => (
<>
<TextInput
onBlur={onBlur}
value={value}
onChangeText={onChange}
style={styles.input}
placeholderTextColor={Colors.SmokeBlue}
placeholder="Enter your Email"
/>
{errors.email && (
<Text style={styles.errorMessage}>
{errors.email.message}
</Text>
)}
</>
)}
name="email"
/>
)}
{signUpMethod === "phoneNumber" && (
<View>
<View style={styles.inline}>
<CountryPicker
disable={false}
animationType={"slide"}
language="en"
containerStyle={styles.pickerStyle}
pickerTitleStyle={styles.pickerTitleStyle}
selectedCountryTextStyle={styles.selectedCountryTextStyle}
countryNameTextStyle={styles.countryNameTextStyle}
pickerTitle={"Country Picker"}
searchBarPlaceHolder={"Search......"}
hideCountryFlag={false}
hideCountryCode={false}
searchBarStyle={styles.searchBarStyle}
countryCode={countryCode}
selectedValue={(text) => {
setCountryCode(text);
}}
/>
<Controller
control={control}
rules={{
required: true,
}}
render={({ field: { onChange, value, onBlur } }) => (
<TextInput
onBlur={onBlur}
value={value}
onChangeText={onChange}
style={styles.phoneInput}
placeholderTextColor={Colors.SmokeBlue}
placeholder="Phone number"
/>
)}
name="phoneNumber"
/>
</View>
{errors.phoneNumber && (
<Text style={styles.errorMessage}>
{errors.phoneNumber.message}
</Text>
)}
</View>
)}
<Controller
control={control}
rules={{ required: true }}
render={({ field: { onChange, value, onBlur } }) => (
<TextInput
onBlur={onBlur}
value={value}
onChangeText={onChange}
style={styles.input}
secureTextEntry={true}
placeholderTextColor={Colors.SmokeBlue}
placeholder="Enter your password"
/>
)}
name="password"
/>
{errors.password && (
<Text style={styles.errorMessage}>{errors.password.message}</Text>
)}
<TouchableOpacity
onPress={handleSubmit(onPressSend)}
style={styles.button}
>
<Text style={styles.login}>Login</Text>
</TouchableOpacity>
.....
);
}
Mohamed Hedi ben salah is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.