touched 属性 未重置

touched property not being reset

我有一个 Formik 表单,我在其中接受用户输入并在提交后 运行 查询。

当我点击搜索按钮时,会呈现一个列表。所有列表项都有自己的按钮。当我第一次单击绿色添加按钮(来自列表项)时,该按钮不起作用。不打印控制台日志的内容。相反,会触发 inputField 的 onBlur 事件。但是,如果我再次单击 + 按钮,它就会工作并打印 no。此问题在 simulators/phones 中可见,而不是在沙盒的 Web 模式中。

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

小吃博览会:

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

[![在此处输入图片描述][1]][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?

可能是因为当你调用Keyboard.dismiss()时你实际上是在散焦输入,这将触发validateOnBlur事件。
因此,当您取消聚焦某个字段(模糊)时,它会尝试验证 (validateOnBlur),并且由于该字段为空,它会显示验证。

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

如果错误应该只在您提交表单时显示,您应该传递给 Formik 组件 validateOnBlur={false}。有了这个,当您调用 Keyboard.dismiss() 时它不会显示错误消息,因为它会删除对模糊的验证。

但是当输入改变时它仍然有效,触发validateOnChange。您还可以传递给 Formik 组件 validateOnChange={false} 以禁用更改验证,它只会在您提交表单(按下按钮)时验证。

请注意validateOnChangevalidateOnBlur默认为true

编辑:

您需要添加 validateOnBlur={false},但您需要调用 fieldRef.current.blur() 而不是调用 Keyboard.dismiss()。但要使其工作,您需要在输入组件中使用 React.forwardRef

所以你需要创建 fieldRef

const fieldRef = useRef();

传递给组件

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

你需要用 React.forwardRef 环绕你的 FieldInput 并将 ref 传递给 Input 组件。

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

而现在在 handleSubmitForm 你调用 fieldRef.current.blur()

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

有了这个,你将解决你的问题和评论中的问题。

Working example

关于useRef

的说明

我们需要使用 useRef 钩子,以便我们可以获取 Input 组件的元素,以便能够调用 blur 函数,所以不要专注于输入并可以单击加号按钮。 我们需要使用 useRef 挂钩,因为这是在功能组件中创建 ref 的方式。