简体   繁体   English

useValidation 挂钩未按预期工作

[英]useValidation hook is not working as expected

I have a signup screen and i have built two costom hooks for it.我有一个注册屏幕,我已经为它构建了两个 costom 挂钩。

  1. useSignup in which my signup method and its local is defined useSignup 在其中定义了我的注册方法及其本地
  2. util hook in which i have defined validation method.我在其中定义了验证方法的 util 钩子。

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:这是 useSignup 钩子:

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:这是 useValidation 钩子:

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?我究竟做错了什么?

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.我想 useSignup 很好,但对我来说 useValidation 听起来不应该绑定到 useSignup 并且可能在其他 forms 以及不同的元素和验证规则中使用。

Code below can be found and tested at https://codesandbox.io/s/musing-vaughan-srw66可以在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.如果您想为 forms 使用自定义钩子,一个想法是使整个表单成为一个钩子。 In the code I am not using useSignup or useValidateor but instead useForm which handles both form elements and event logic.在代码中,我没有使用 useSignup 或 useValidateor,而是使用处理表单元素和事件逻辑的 useForm。 Default values can either be added as an optional third argument to useForm or in value prop on form element with values.email ||默认值可以作为可选的第三个参数添加到 useForm 或在带有值的表单元素的 value 属性中添加。email || 'test@testson.com'. 'test@testson.com'。 I have also outsourced the validate function so that useForm can be used with any form and validate method to make it reusable.我还外包了验证 function 以便 useForm 可以与任何表单和验证方法一起使用以使其可重用。

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来自https://upmostly.com/tutorials/form-validation-using-custom-react-hooks的想法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM