user12541823
user12541823

Reputation:

Unable to Type in <Formik> Field

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>
  );
};

Why am I unable to write anything inside my Input field? I have tried using onChangeand handleChangeboth but it doesn't make a difference. Other SO answers suggested that I should remove value but examples of Formik usage that I see online suggest otherwise.

I am trying to follow this for my Formik validation:

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

EDIT: I also tried with setFieldValuebut I still cannot type anything.

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>
  );
};

Upvotes: 4

Views: 4712

Answers (4)

sernaferna
sernaferna

Reputation: 354

Formik now works fine with React Native, but another thing to be aware of is that the name in your form control must match the name of the property in the schema used by Formik.

For example, if using the following Yup schema:

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

Then the following won't work because the Yup schema (personName) and the form control (nameofPerson) don't match; the user won't be able to type into the field:

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

To make it work, the name should be the same as the Yup property; in this case, personName:

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

This example is using React-Bootstrap Form.Control but should apply to any manner of creating form controls.

Upvotes: 0

Ritesh Bansal
Ritesh Bansal

Reputation: 3248

I think there are a couple of issues in your codebase.

  1. onChangeText={handleChange('friendEmail')}. It will trigger the handleChange while rendering the component not when you are actualy typing in the input box.
  2. handleChange function of Formik takes React.ChangeEvent instead of value. Check here . While onChangeText of react-native provides changed text of the input not event. Check here

You can use setFieldValue function for this case:

<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>

Please Note: I've never used formik with react-native. Just trying to connect the dots.

Upvotes: 0

Lokesh
Lokesh

Reputation: 301

try this:

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

Upvotes: 0

Shubham Khatri
Shubham Khatri

Reputation: 281734

Formik's Field component doesn't support React native yet. Check this github issue for more details

However you can make use of TextInput in place of field and use it with onChangeText handler

<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>

you can read more about Formik's usage with react-native in its documentation here

Upvotes: 1

Related Questions