Aqsa Maan
Aqsa Maan

Reputation: 115

useValidation hook is not working as expected

I have a signup screen and i have built two costom hooks for it.

  1. useSignup in which my signup method and its local is defined
  2. util hook in which i have defined validation method.

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

Answers (1)

Bjorne
Bjorne

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

Related Questions