首页 > 解决方案 > 原生基础输入的 Formik 验证

问题描述

我正在使用本机基础的输入字段,并尝试使用 Formik 和 Yup 对其进行验证。但是,到目前为止还没有进行验证。即使我输入字母,它也不会显示任何错误。

此代码有效(没有 Formik):

type EmailRegistrationProps = {};

interface FormValues {
  friendEmail: string;
}

type AddFriendEmailPageProps = {
  toggleShowPage: () => void;
  showAddFriendEmailPage: boolean;
};

export const AddFriendEmailPage: React.FunctionComponent<AddFriendEmailPageProps> = ({
  toggleShowPage,
  showAddFriendEmailPage,
}) => {
  const [friendEmail, setFriendEmail] = useState('');
  const [errorMessage, setErrorMessage] = useState('');
  const validationSchema = emailValidationSchema; 

  const showAlert = () => {
    Alert.alert('Friend Added');
  }

  useEffect(() => {
    if (showAddFriendEmailPage) return;
    setFriendEmail('');
  }, [showAddFriendEmailPage]);

  const _onLoadUserError = React.useCallback((error: ApolloError) => {
    setErrorMessage(error.message);
    Alert.alert('Unable to Add Friend');
  }, []);

  const [
    createUserRelationMutation,
    {
      data: addingFriendData,
      loading: addingFriendLoading,
      error: addingFriendError,
      called: isMutationCalled,
    },
  ] = useCreateUserRelationMutation({
    onCompleted : ( data: any) => {
      showAlert();
    }
  });

  const addFriend = React.useCallback(
    (id: Number) => {
      console.log('Whats the Id', id);
      createUserRelationMutation({
        variables: {
          input: { relatedUserId: id, type: RelationType.Friend, userId: 7 },
        },
      });
    },
    [createUserRelationMutation],
  );

  const getFriendId = React.useCallback(
    (data: any) => {
      console.log('Email', friendEmail);
      if (data) {
        if (data.users.nodes.length == 0) {
          setErrorMessage('User Not Found');
        } else {
          addFriend(Number(data.users.nodes[0].id));
        }
      }
    },
    [friendEmail, addFriend],
  );

  const [loadUsers] = useUsersLazyQuery({
    onCompleted: getFriendId,
    onError: _onLoadUserError,
  });

  const handleSubmit = React.useCallback(() => {
    loadUsers({
      variables: {
        where: { email: friendEmail },
      },
    });
    setFriendEmail('');
  }, [loadUsers, friendEmail]);

  }


  return (
    <Modal
      visible={showAddFriendEmailPage}
      animationType="slide"
      transparent={true}>
      <SafeAreaView>
        <View style={scaledAddFriendEmailStyles.container}>
          <View style={scaledAddFriendEmailStyles.searchTopContainer}>
            <View style={scaledAddFriendEmailStyles.searchTopTextContainer}>
              <Text
                style={scaledAddFriendEmailStyles.searchCancelDoneText}
                onPress={toggleShowPage}>
                Cancel
              </Text>
              <Text style={scaledAddFriendEmailStyles.searchTopMiddleText}>
                Add Friend by Email
              </Text>
              <Text style={scaledAddFriendEmailStyles.searchCancelDoneText}>
                Done
              </Text>
            </View>
            <View style={scaledAddFriendEmailStyles.searchFieldContainer}>
              <Item style={scaledAddFriendEmailStyles.searchField}>
                <Input
                  placeholder="Email"
                  style={scaledAddFriendEmailStyles.searchText}
                  onChangeText={(text) => setFriendEmail(text)}
                  value={friendEmail}
                  autoCapitalize="none"
                />
              </Item>
              <View style={scaledAddFriendEmailStyles.buttonContainer}>
                <Button
                  rounded
                  style={scaledAddFriendEmailStyles.button}
                  onPress={() => handleSubmit()}
                >
                  <Text style={scaledAddFriendEmailStyles.text}>
                    Add Friend{' '}
                  </Text>
                </Button>
              </View>
              {/* </View>
                )}
              </Formik> */}
            </View>
          </View>
        </View>
      </SafeAreaView>
    </Modal>
  );
};

现在我正在尝试添加 Formik:

编辑:

export const AddFriendEmailPage: React.FunctionComponent<AddFriendEmailPageProps> = ({
  toggleShowPage,
  showAddFriendEmailPage,
}) => {
  const initialValues: FormValues = {
    friendEmail: '',
  };

  //const [friendEmail, setFriendEmail] = useState('');
  const [errorMessage, setErrorMessage] = useState('');
  const validationSchema = emailValidationSchema; 

  const showAlert = () => {
    Alert.alert('Friend Added');
  }

  useEffect(() => {
    if (showAddFriendEmailPage) return;
    initialValues.friendEmail = '';
  }, [showAddFriendEmailPage]);

  const _onLoadUserError = React.useCallback((error: ApolloError) => {
    setErrorMessage(error.message);
    Alert.alert('Unable to Add Friend');
  }, []);

  const [
    createUserRelationMutation,
    {
      data: addingFriendData,
      loading: addingFriendLoading,
      error: addingFriendError,
      called: isMutationCalled,
    },
  ] = useCreateUserRelationMutation({
    onCompleted : ( data: any) => {
      showAlert();
    }
  });

  const addFriend = React.useCallback(
    (id: Number) => {
      console.log('Whats the Id', id);
      createUserRelationMutation({
        variables: {
          input: { relatedUserId: id, type: RelationType.Friend, userId: 7 },
        },
      });
    },
    [createUserRelationMutation],
  );

  const getFriendId = React.useCallback(
    (data: any) => {
      console.log('Email', friendEmail);
      if (data) {
        if (data.users.nodes.length == 0) {
          console.log('No user');
          setErrorMessage('User Not Found');
          Alert.alert('User Not Found');
        } else {
          console.log('ID', data.users.nodes[0].id);
          addFriend(Number(data.users.nodes[0].id));
        }
      }
    },
    [friendEmail, addFriend],
  );

  const [loadUsers] = useUsersLazyQuery({
    onCompleted: getFriendId,
    onError: _onLoadUserError,
  });

  const handleSubmit = React.useCallback((
    values: FormValues,
    helpers: FormikHelpers<FormValues>,
    ) => {
    console.log('Submitted');
    loadUsers({
      variables: {
        where: { email: values.friendEmail },
      },
    });
    //setFriendEmail('');
    values.friendEmail = '';
  }, [loadUsers, initialValues.friendEmail]);
  }


  return (
    <Modal
      visible={showAddFriendEmailPage}
      animationType="slide"
      transparent={true}>
      <SafeAreaView>
        <View style={scaledAddFriendEmailStyles.container}>
          <View style={scaledAddFriendEmailStyles.searchTopContainer}>
            <View style={scaledAddFriendEmailStyles.searchTopTextContainer}>
              <Text
                style={scaledAddFriendEmailStyles.searchCancelDoneText}
                onPress={toggleShowPage}>
                Cancel
              </Text>
              <Text >
                Add Friend by Email
              </Text>
              <Text>
                Done
              </Text>
            </View>
            <View style={scaledAddFriendEmailStyles.searchFieldContainer}>
               <Formik
                initialValues={initialValues}
                onSubmit={handleSubmit}
                validationSchema={validationSchema}>
                {({
                  handleChange,
                  handleBlur,
                  handleSubmit,
                  isSubmitting,
                  values,
                }) => ( 
                  <Field
                  component={Input}
                  placeholder="Email"
                  onChangeText={handleChange('friendEmail')}
                  onBlur={handleBlur('friendEmail')}
                  value={values.friendEmail}
                  autoCapitalize="none"
                  />
                )}
                </Formik>
              <View >
                <Button
                  onPress={() => handleSubmit()}
                >
                  <Text >
                    Add Friend{' '}
                  </Text>
                </Button>
              </View>
            </View>
          </View>
        </View>
      </SafeAreaView>
    </Modal>
  );
};

目前,这对我不起作用。我想继续使用通过按钮的 onPress 使用的旧 handleSubmit。但现在我不知道如何将值、助手传递到这个句柄提交中:

onPress={() => handleSubmit()}

我明白了Expected 2 arguments, but got 0.

但是如果我试图通过values, helpers这些名字都找不到。同样,我正在使用

[friendEmail, addFriend],

在结束时getFriendId。如果我只使用 setState 而没有 formik 验证等,这可以正常工作。但现在friendEmail找不到。我只是无法以这样一种方式正确合并 Formik,以至于我也可以像使用useState.

标签: javascripttypescriptreact-nativeformiknative-base

解决方案


Formik requires you to utilize the <Field /> component for validation.

<Field /> will automagically hook up inputs to Formik. It uses the name attribute to match up with Formik state. <Field /> will default to an HTML <input /> element.

You can set custom components via the component prop.

In your case, for example:

<Field
    component={Input}
    name="phoneNumber"
    placeholder="Phone Number"
    onChangeText={handleChange}
    onBlur={handleBlur}
    type='tel'
    value={values.phoneNumber}
/>

Update

Ahh, my bad, I updated the onChangeText and onBlur to reflect the changes. In the current implementation you're actually running the "handle" events on load rather than when the even occurs. If you name the input it should pass that information along automagically. Also, you should set a type for the input. I've updated the above example for all of these updates.


推荐阅读