无法输入 <Formik> 字段

Posted

技术标签:

【中文标题】无法输入 <Formik> 字段【英文标题】:Unable to Type in <Formik> Field 【发布时间】:2020-08-22 19:09:45 【问题描述】:
interface FormValues 
  friendEmail: string;


  const initialValues: FormValues = 
    friendEmail: '',
  ;

export const Page: React.FunctionComponent<PageProps> = (
  toggleShowPage,
  showPage,
) => 

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

  useEffect(() => 
    if (showPage) return;
    initialValues.friendEmail = '';
  , [showPage]);

  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', initialValues.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));
        
      
    ,
    [addFriend],
    //[friendEmail, addFriend],
  );

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

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

  if (!addingFriendLoading && isMutationCalled) 
    if (addingFriendData) 
      console.log('Checking');
    
    if (addingFriendError) 
      console.log('errorFriend', addingFriendError.message);
    
  

  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>
              <Formik
                initialValues=initialValues
                onSubmit=handleSubmitForm
                validationSchema=validationSchema>
                (
                  handleChange,
                  handleBlur,
                  handleSubmit,
                  isSubmitting,
                  values,
                ) => (
                  <View>
                    <View>

                      <Item style=scaledAddFriendEmailStyles.searchField>
                      <TextInput
                      style=scaledAddFriendEmailStyles.searchText
                      placeholder="Email"
                      onChangeText=handleChange('friendEmail')
                      //onChangeText=e => console.log('Workinggg')
                      onBlur=handleBlur('friendEmail')
                      value=values.friendEmail
                      autoCapitalize="none"
                      />
                        /* <Field
                          component=Input
                          name='friendEmail'
                          placeholder="Email"
                          //handleChange=handleChange
                          handleBlur=handleBlur
                          //onChange=handleChange                         
                          //onChangeText=handleChange('friendEmail')
                          //onBlur=handleBlur('friendEmail')
                          value=values.friendEmail
                          autoCapitalize="none"
                        /> */
                      </Item>
                    </View>
                    <View>
                      <Button                        
                        onPress=handleSubmit>
                        <Text>
                          Add Friend' '
                        </Text>
                      </Button>
                    </View>
                  </View>
                )
              </Formik>
            </View>
          </View>
        </View>
      </SafeAreaView>
    </Modal>
  );
;

为什么我无法在输入字段中写入任何内容?我尝试过使用onChangehandleChangeboth,但这并没有什么不同。其他 SO 答案建议我应该删除 value,但我在网上看到的 Formik 用法示例另有说明。

我正在尝试按照这个进行我的 Formik 验证:

https://heartbeat.fritz.ai/build-and-validate-forms-in-react-native-using-formik-and-yup-6489e2dff6a2

编辑: 我也尝试过setFieldValue,但我仍然无法输入任何内容。

const initialValues: FormValues = 
  friendEmail: '',
;

export const AddFriendEmailPage: React.FunctionComponent<AddFriendEmailPageProps> = (
  toggleShowPage,
  showAddFriendEmailPage,
) => 

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

  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', initialValues.friendEmail);
      if (data) 
        if (data.users.nodes.length == 0) 
          console.log('No user');
         else 
          console.log('ID', data.users.nodes[0].id);
          addFriend(Number(data.users.nodes[0].id));
        
      
    ,
    [addFriend],
    //[friendEmail, addFriend],
  );

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

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

  return (
    <Modal
      visible=showPage
      animationType="slide"
      transparent=true>
      <SafeAreaView>
        <View style=scaledAddFriendEmailStyles.container>
            <View style=scaledAddFriendEmailStyles.searchFieldContainer>
              <Formik
                initialValues=initialValues
                onSubmit=handleSubmitForm
                validationSchema=validationSchema>
                (
                  handleChange,
                  setFieldValue,
                  handleBlur,
                  handleSubmit,
                  isSubmitting,
                  values,
                ) => 
                  const setEmail = (friendEmail: string) => 
                    setFieldValue('friendEmail', friendEmail)
                  
                return(
                  <View>
                    <View>

                      <Item>
                      <TextInput                     
                      placeholder="Email"
                      onChangeText=setEmail
                      onBlur=handleBlur('friendEmail')
                      value=values.friendEmail
                      autoCapitalize="none"
                      />
                      </Item>
                    </View>
                    <View >
                      <Button
                        onPress=handleSubmit>
                        <Text >
                          Add Friend' '
                        </Text>
                      </Button>
                    </View>
                  </View>
                )
              </Formik>
            </View>
          </View>
        </View>
      </SafeAreaView>
    </Modal>
  );
;

【问题讨论】:

onChange=handleChange 应该可以工作。不要使用handleChange=handleChange 已经尝试过了,但没有用@ShubhamKhatri 按功能划分 - 将 formik/form 逻辑移动到自己的组件中,在内部使用useFormik ...传递handleSubmitForm [或loadUsers] 作为道具 【参考方案1】:

Formik 的 Field 组件还不支持 React native。更多详情请查看this github issue

但是,您可以使用 TextInput 代替字段并将其与 onChangeText 处理程序一起使用

<Formik
    initialValues=initialValues
    onSubmit=handleSubmitForm
    validationSchema=validationSchema>
    (
      handleChange,
      handleBlur,
      handleSubmit,
      isSubmitting,
      values,
    ) => (
      <View>
        <View>
          <Item style=scaledAddFriendEmailStyles.searchField>
            <TextInput
              placeholder="Email"
              onChangeText=handleChange('friendEmail')
              onBlur=handleBlur('friendEmail')
              value=values.friendEmail
            />
          </Item>
        </View>
        <View >
          <Button 
          onPress=handleSubmit
          >
            <Text >
              Add Friend' '
            </Text>
          </Button>
        </View>
      </View>
    )
  </Formik>

您可以在其documentation here 中阅读更多有关 Formik 与 react-native 的用法

【讨论】:

我仍然无法在此 TextField 中输入任何内容。也许问题出在代码中的其他地方 有什么想法吗? 哦,天哪,这很难指出。尝试键入字符时是否有任何重新渲染。可能是因为您直接在功能组件中定义了初始值,并且每次键入字符时引用都会更改。尝试将其移出组件,看看您是否仍然遇到问题 将初始值移到外面也不起作用。我认为我没有在其他任何地方使用另一个显式渲染。我在上面添加了完整的代码【参考方案2】:

试试这个:

<Input
  placeholder="Email"
  onChange=e => setFieldValue('friendEmail', e.currentTarget.value)
  onBlur=handleBlur
  value=values.friendEmail
  autoCapitalize="none"
/>

【讨论】:

输入没有名称属性。即使我将其注释掉,我仍然无法输入任何内容。 如果您注释掉名称,则 handleChange 将不起作用。如果您要从字段中删除名称,只需尝试 onChange=e =&gt; setFieldValue('friendEmail', e.currentTarget.value) 这给了我Property 'value' does not exist on type 'number'.。这很奇怪,因为我没有在任何地方使用数字...... 尝试给e输入any,如果有效,然后将any更改为事件的类型。 onChange=(e: any) =&gt; setFieldValue('friendEmail', e.currentTarget.value)【参考方案3】:

我认为您的代码库中有几个问题。

    onChangeText=handleChange('friendEmail')。它会在渲染组件时触发handleChange,而不是在您实际在输入框中输入时。 FormikhandleChange 函数采用 React.ChangeEvent 而不是值。检查here。而onChangeTextreact-native 提供输入的更改文本而不是事件。检查here

您可以在这种情况下使用setFieldValue 函数:

<Formik
    initialValues=initialValues
    onSubmit=handleSubmitForm
    validationSchema=validationSchema>
    (
      handleChange,
      handleBlur,
      handleSubmit,
      isSubmitting,
      values,
      setFieldValue
    ) => 
    const setEmail = (email) => 
      setFieldValue('friendEmail', email)
    
    return (
      <View>
        <View>
          <Item style=scaledAddFriendEmailStyles.searchField>
            <TextInput
              placeholder="Email"
              onChangeText=setEmail
              value=values.friendEmail
            />
          </Item>
        </View>
      </View>
    )
    
  </Formik>

请注意:我从未将formikreact-native 一起使用。只是想把这些点联系起来。

【讨论】:

它对我还不起作用。也许问题出在其他地方。我编辑了 qs 以添加我的完整代码。另外,这样就没有用handleChangeinto Formik right【参考方案4】:

Formik 现在可以很好地与 React Native 配合使用,但需要注意的另一件事是表单控件中的 name 必须与 Formik 使用的架构中的属性名称匹配。

例如,如果使用以下 Yup 架构:

const schema = yup.object(
  personName: yup.string().required('Name required')
);

那么以下内容将不起作用,因为 Yup 架构 (personName) 和表单控件 (nameofPerson) 不匹配;用户将无法在该字段中输入:

<Form.Control
  name="nameOfPerson"
  value=values.personName
  onChange=handleChange
  onBlur=handleBlur
  type="text"
  isValid=!errors.personName && !!touched.personName
  isInvalid=!!errors.personName && !!touched.personName
/>

要使其工作,name 应该与 Yup 属性相同;在这种情况下,personName:

<Form.Control
  name="personName"
  value=values.personName
  onChange=handleChange
  onBlur=handleBlur
  type="text"
  isValid=!errors.personName && !!touched.personName
  isInvalid=!!errors.personName && !!touched.personName
/>

此示例使用 React-Bootstrap Form.Control,但应适用于任何创建表单控件的方式。

【讨论】:

以上是关于无法输入 <Formik> 字段的主要内容,如果未能解决你的问题,请参考以下文章

Formik,多步表单制作按钮禁用

如何通过打字稿在Formik中添加强类型字段?

Formik 中如何保存输入字段中的数据

无法覆盖 formik Select 的 `onChange` 处理程序

Formik Yup `.test()` 自定义验证无法正常工作

使用带有formik的react-select时无法读取未定义的属性“类型”