Reactjs useValidation挂钩未按预期工作

Reactjs useValidation挂钩未按预期工作,reactjs,react-native,react-hooks,Reactjs,React Native,React Hooks,我有一个注册屏幕,我为它建立了两个costom挂钩 useSignup,其中定义了我的注册方法及其局部 util钩子,我在其中定义了验证方法 但我无法按预期使用验证方法。 这是注册屏幕 import React, {useState} from 'react'; import { View, Text, StatusBar, Keyboard, TouchableOpacity, ScrollView, } from 'react-native'; import Icon

我有一个注册屏幕,我为它建立了两个costom挂钩

  • useSignup,其中定义了我的注册方法及其局部
  • util钩子,我在其中定义了验证方法
  • 但我无法按预期使用验证方法。 这是注册屏幕

    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;
    
    下面是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];
    };
    

    我做错了什么?

    不完全确定你想要完成什么。对于我来说,定制钩子应该是可重用的,并且描述它们的响应。我想useSignup很好,但是useValidation对我来说听起来似乎不应该与useSignup绑定,并且可能在其他形式中使用不同的元素和验证规则

    以下代码可在以下位置找到并测试:

    如果您想对表单使用自定义钩子,一个想法是将整个表单变成一个钩子。在代码中,我没有使用useSignup或useValidateor,而是使用useForm,它处理表单元素和事件逻辑。可以将默认值作为可选的第三个参数添加到useForm中,也可以将默认值添加到带有values.email | |'的表单元素中的value prop中test@testson.com'. 我还外包了validate函数,以便useForm可以与任何表单和validate方法一起使用,从而使其可重用

    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 | |!values.email)错误.push(“必须指定电子邮件”);
    const emailRegex=/^([^()[\]\\,;:\s@“]+(\.[^()[\]\,;:\s@“]+)*)(“+”)(\[[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[1,3}.[0-9]{1,3}.]124;([a-zA Z-0-9]++]2});
    if(!emailRegex.test(字符串(values.email.toLowerCase()))
    错误。推送(“电子邮件无效”);
    //价值的其他验证
    返回错误;
    };
    导出默认函数表单(){
    const{values,errors,setValue,handleSubmit}=useForm(
    formValidatior,
    扶手电梯成功提交
    //{email:“test”}//添加初始值或非形式值的可能性
    );
    函数handleValidationSuccessOnSubmit(){
    console.log(“通过验证”);
    }
    返回(
    电子邮件
    setValue(event.target.name,event.target.value)}
    value={values.email | |“}/”成为默认值
    />
    {errors?errors.map((error)=>{error}

    ):null} ); }

    Idea from

    在注册组件中,您使用useSignup返回许多状态。但是你也有useValidation,这反过来会创建一个新的useSignup。更新注册组件中的状态时,useValidation中的状态不会更新。基本上,您有两种不同的注册状态。
    useSignup
    返回一个包含12项的数组,
    useValidation
    仅对其中6项进行分解,并且您使用的那些项不对应。建议您使用对象而不是数组。@请更正代码。如果我能看到代码的变化,我很容易理解我的错误。我理解其中一些,但不知道如何解决它,因为这是我第一次与custom交互hooks@WillJenkins钩子不是只对数组有效吗?@aqsaman-Nope,你可以随意返回。
    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>
      );
    }