touched property not being reset

十年热恋 提交于 2021-01-28 20:49:06

问题


I have a Formik form where I take user input input & run a query after submitting.

When I click on the search button, a list is rendered. All list items have a button of their own. When I click on the green add button (from the list items) for the first time, the button does not work. Console log's content is not printed. Instead, the onBlur event of the inputField is triggered. However, if I click on the + button again, then it works and prints no. This problem is visible in simulators/phones, not on the web mode on the sandbox.

export const AddFriendScreen: React.FunctionComponent = () => {
  const initialValues: FormValues = {
    input: '',
  };

  const [showFlatList, setShowFlatList] = useState<UsersLazyQueryHookResult>(
    '',
  );


  const handleSubmitForm = (
    values: FormValues,
    helpers: FormikHelpers<FormValues>,
  ) => {

    loadUsers({
      variables: {
        where: {
          OR: [
            { phoneNumber: newPhoneNumber },],
        },
      },
    });
    helpers.resetForm();
 };

  return (
    <SafeAreaView style={styles.safeAreaViewContainer}>
      <View style={styles.searchTopContainer}>
        <View style={styles.formContainer}>
          <Formik
            initialValues={initialValues}
            onSubmit={handleSubmitForm}
            validationSchema={validationSchema}>
            {({ handleChange, handleBlur, handleSubmit, values }) => (
              <View style={styles.searchFieldContainer}>
                <View style={styles.form}>
                  <FieldInput
                    handleChange={handleChange}
                    handleBlur={handleBlur}
                    value={values.input}
                    fieldType="input"
                    icon="user"
                    placeholderText="E-Mail oder Telefonnummer oder Name"
                  />
                  <ErrorMessage
                    name="input"
                    render={(msg) => <ErrorText errorMessage={msg} />}
                  />
                </View>
                <View style={styles.buttonContainer}>
                  <ActionButton buttonText="Suchen" onPress={handleSubmit} />
                </View>
              </View>
            )}
          </Formik>
        </View>
        <View style={styles.listHolder}>
          {data && showFlatList !== null && (
            <UsersFoundList
              data={data}/>
          )}
        </View>
      </View>
    </SafeAreaView>
  );
};

Snack Expo:

https://snack.expo.io/@nhammad/jealous-beef-jerky

[![enter image description here][1]][1]

Edit:

Found a workaround but still open to easier solutions. Still haven't figured out what's causing the issue exactly.


回答1:


However, this causes the formik error to show up immediately after the form is submitted and data is returned/rendered. For instance, the error suggests that the input field should not be empty.
...
Why is the keyboard interfering in this?

Probably because when you call Keyboard.dismiss() you are actually unfocusing the input, which will trigger the validateOnBlur event.
So when you unfocus a field (blur), it will try to validate (validateOnBlur), and because the field is empty, it will show the validation.

The error should only show up when we are trying to resubmit the form without an input.

If the error should only show when you submit the form, you should pass to the Formik component validateOnBlur={false}. With this, it won't show the error message when you call Keyboard.dismiss(), because it will remove the validation on blur.

But it still validates when the input changes, triggering validateOnChange. You can also pass to the Formik component validateOnChange={false} to disable the validation on change and it will only validate when you submit the form (press the button).

Please notice that validateOnChange and validateOnBlur are true by default.

Edit:

You need to add validateOnBlur={false} but instead of calling Keyboard.dismiss() you need to call fieldRef.current.blur(). But for that to work, you need to use React.forwardRef in your input component.

So you need to create the fieldRef

const fieldRef = useRef();

Pass to the component

<FieldInput
    ref={fieldRef} // passing the ref
    handleChange={handleChange}
    handleBlur={handleBlur}
    value={values.input}
    fieldType="input"
    icon="user"
    placeholderText="input"
/>

And you need to wrap around your FieldInput with React.forwardRef and pass the ref to the Input component.

// wrapping the component with React.forwardRef
export const FieldInput: React.FunctionComponent<FieldInputProps> = React.forwardRef(({
  handleChange,
  handleBlur,
  fieldType,
  placeholderText,
  value,
  style,
  rounded,
  //ref,
}, ref) => {
  return (
    <Item rounded={rounded} style={[styles.inputItem, style]}>
      <Input
        ref={ref} // passing the ref 
        autoFocus={true}
        autoCapitalize="none"
        style={styles.inputField}
        placeholder={placeholderText}
        keyboardType="default"
        onChangeText={handleChange(fieldType)}
        onBlur={handleChange(fieldType)}
        value={value}
      />
    </Item>
  );
});

And now in the handleSubmitForm you call fieldRef.current.blur()

const handleSubmitForm = (
    values: FormValues,
    helpers: FormikHelpers<FormValues>,
) => {
    // other logic from your submit
    if (fieldRef && fieldRef.current)
          fieldRef.current.blur();
};

With this, you will solve the problems of your question and from the comments.

Working example

Explanation about useRef

We need to use the useRef hook so we can get the element of the Input component to be able to call the blur function so don't be focused in the input and can click in the plus button. We need to use the useRef hook because that is how you create a ref in functional components.



来源:https://stackoverflow.com/questions/63667170/touched-property-not-being-reset

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!