Reputation: 115
I have a signup screen and i have built two costom hooks for it.
but i'm unable to use validation method as expected. here is signup screen
import React, {useState} from 'react';
import {
View,
Text,
StatusBar,
Keyboard,
TouchableOpacity,
ScrollView,
} from 'react-native';
import Icon from 'react-native-vector-icons/AntDesign';
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
import Input from '../../../components/input';
import Btn from '../../../components/button';
import CheckBox from '../../../components/checkbox';
import PressableText from '../../../components/pressable';
import {styles} from './style';
import useSignup from './customHooks/useSignup';
import useValidation from './customHooks/utils';
const Signup = ({navigation}) => {
const [
id,
setId,
name,
setName,
email,
setEmail,
pass,
setPass,
confirmPass,
setConfirmPass,
validated,
setValidated,
] = useSignup();
const [validation] = useValidation();
return (
<View style={styles.container}>
<StatusBar barStyle="dark-content" />
<TouchableOpacity activeOpacity={1} onPress={() => Keyboard.dismiss()}>
<ScrollView contentContainerStyle={styles.ScrollView}>
<View style={styles.backIconView}>
<Icon
name="arrowleft"
size={40}
color={'#807D89'}
onPress={() => navigation.goBack()}
/>
</View>
<View style={styles.textView}>
<Text style={styles.heading}>Create Account</Text>
<Text style={styles.para}>Please fill input below to continue</Text>
</View>
<KeyboardAwareScrollView
resetScrollToCoords={{x: 0, y: 0}}
contentContainerStyle={styles.loginForm}>
<Input
text="ID"
placeholder="Enter Your ID"
keyboardType="number-pad"
icon="key"
secureTextEntry={false}
value={id}
onChangeText={(e) => setId(e)}
/>
<Input
text="Full Name"
placeholder="Enter Name"
keyboardType="default"
icon="user"
secureTextEntry={false}
value={name}
onChangeText={(e) => {
setName(e);
}}
/>
<Input
text="Email"
placeholder="Enter Email"
keyboardType="email-address"
icon="mail"
secureTextEntry={false}
value={email}
onChangeText={(e) => setEmail(e)}
/>
<Input
text="Password"
placeholder="Enter Password"
keyboardType="default"
icon="lock"
secureTextEntry={true}
value={pass}
onChangeText={(e) => setPass(e)}
/>
<Input
text="Confirm Password"
placeholder="Enter Password"
keyboardType="default"
icon="lock"
secureTextEntry={true}
value={confirmPass}
onChangeText={(e) => setConfirmPass(e)}
/>
<View style={styles.checkboxView}>
<CheckBox />
<View style={{flexDirection: 'row'}}>
<Text style={{...styles.signUpViewText, fontSize: 20}}>
I accept all{' '}
</Text>
<PressableText
text={'Terms and Conditions'}
fontSize={18}
action={() => alert('Terms')}
/>
</View>
</View>
<Btn
text="Sign Up"
action={() => {
validation();
if (validated) {
useSignup();
navigation.navigate('Home');
}
}}
/>
</KeyboardAwareScrollView>
<View style={styles.signUpView}>
<Text style={styles.signUpViewText}>Already have an account? </Text>
<PressableText
text="LogIn"
fontSize={18}
action={() => navigation.navigate('Login')}
/>
</View>
</ScrollView>
</TouchableOpacity>
</View>
);
};
export default Signup;
here is useSignup hook:
import React, {useState} from 'react';
import auth from '@react-native-firebase/auth';
export default useSignup = () => {
// auth()
// .createUserWithEmailAndPassword(email, pass)
// .then(() => {
// console.log('User account created & signed in!');
// alert(`signed in with ${email}`);
// })
// .catch((error) => {
// if (error.code === 'auth/email-already-in-use') {
// console.log('That email address is already in use!');
// }
// if (error.code === 'auth/invalid-email') {
// console.log('That email address is invalid!');
// }
// console.error(error);
// });
// console.log(email, 'email');
// console.log(pass, 'pass');
const [id, setId] = useState('');
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [pass, setPass] = useState('');
const [confirmPass, setConfirmPass] = useState('');
const [validated, setValidated] = useState(false);
console.log(id, 'in signup');
return [
id,
setId,
name,
setName,
email,
setEmail,
pass,
setPass,
confirmPass,
setConfirmPass,
validated,
setValidated,
];
};
and here is useValidation hook:
import useSignup from './useSignup';
export default useValidation = () => {
const [id, name, email, pass, confirmPass, setValidated] = useSignup();
console.log(id, 'in utils');
const validation = () => {
id == ''
? alert('Enter ID')
: name == '' || email == ''
? alert('User not Found')
: pass == '' || confirmPass == ''
? alert('enter Password')
: pass != confirmPass
? alert('Pass does not match')
: setValidated(true);
};
return [validation];
};
What am i doing wrong?
Upvotes: 0
Views: 675
Reputation: 1484
Not entierly sure what you want to accomplish. For me custom hooks should be reusable and descriptive of their response. The useSignup I guess is fine but useValidation to me sounds like it should not be bound to useSignup and may possibly be used in other forms aswell with different elements and validation rules.
Code below can be found and tested at https://codesandbox.io/s/musing-vaughan-srw66
If you want to use custom hooks for forms an idea is to make the entire form a single hook. In the code I am not using useSignup or useValidateor but instead useForm which handles both form elements and event logic. Default values can either be added as an optional third argument to useForm or in value prop on form element with values.email || '[email protected]'. I have also outsourced the validate function so that useForm can be used with any form and validate method to make it reusable.
useForm.js
const useForm = (validate, onSubmit, initalValues) => {
const [values, setValues] = useState(initalValues ? initalValues : {});
const [errors, setErrors] = useState([]);
const [isSubmitting, setIsSubmitting] = useState(false);
useEffect(() => {
if (Object.keys(errors).length === 0 && isSubmitting) onSubmit();
setIsSubmitting(false);
}, [errors]);
const handleSubmit = (event) => {
event.preventDefault();
setErrors(validate(values));
setIsSubmitting(true);
};
const setValue = (name, value) => {
setValues((values) => ({
...values,
[name]: value
}));
};
return {
setValue,
handleSubmit,
values,
errors
};
};
App.js
const formValidatior = (values) => {
const errors = [];
if (!values || !values.email) errors.push("Email must be specified");
const emailRegex = /^(([^<>()[\]\\.,;:\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,}))$/;
if (!emailRegex.test(String(values.email).toLowerCase()))
errors.push("Email not valid");
//Other validation of values
return errors;
};
export default function Form() {
const { values, errors, setValue, handleSubmit } = useForm(
formValidatior,
handleValidationSuccessOnSubmit
//{ email: "test" } //possibility to add initial values or nonform values
);
function handleValidationSuccessOnSubmit() {
console.log("PASSED VALIDATION");
}
return (
<div>
<form onSubmit={handleSubmit}>
<label>Email</label>
<input
type="text"
name="email"
placeholder="Your email..."
onChange={(event) => setValue(event.target.name, event.target.value)}
value={values.email || ""} // "" becomes default value
/>
<input type="submit" value="Submit" />
{errors ? errors.map((error) => <p>{error}</p>) : null}
</form>
</div>
);
}
Idea from https://upmostly.com/tutorials/form-validation-using-custom-react-hooks
Upvotes: 1