使用自定义组件时不会触发 onChange 处理程序

onChange handler doesn't fire when using custom-component

我正在使用 Formik 在 React 应用程序中进行验证。

验证工作正常,但我的 onChange 处理程序没有触发:

  <Field
    type="text"
    name="name"
    placeholder="First Name"
    component={Input}
    onChange={() => console.log("gfdg")}
  />

Link to Sandbox

这是为什么?

Input 中,您对传递给输入元素的 props 进行排序的方式意味着您的 onChange 正在被 Formik 的 onChange 覆盖。当您使用自定义组件创建 Field 时(即在您的情况下为 Input ),Formik 将其 FieldProps 传递给该组件。 FieldProps 包含 属性 field,其中包含各种处理程序,包括 onChange.

在你的 Input 组件中你这样做(我已经删除了不相关的道具):

<input
    onChange={onChange}
    {...field}
/>

看看您自己的 onChange 将如何被 field 中 Formik 的 onChange() 取代?为了更清楚 ...field 基本上是导致这种情况发生的原因:

<input
    onChange={onChange}
    onChange={field.onChange}
    // Other props inside "field".
/>

如果您要重新排序,现在将显示控制台消息:

<input
    {...field}
    onChange={onChange}
/>

但是现在您的输入现在不起作用,因为您确实需要调用 Formik 的 onChange 让 Formik 在您的输入发生变化时立即生效。如果您希望自定义 onChange 事件和您的输入都能正常工作,您可以这样做:

import React from "react";
import { color, scale } from "./variables";

const Input = React.forwardRef(
  ({ onChange, onKeyPress, placeholder, type, label, field, form }, ref) => (
    <div style={{ display: "flex", flexDirection: "column" }}>
      {label && (
        <label style={{ fontWeight: 700, marginBottom: `${scale.s2}rem` }}>
          {label}
        </label>
      )}
      <input
        {...field}
        ref={ref}
        style={{
          borderRadius: `${scale.s1}rem`,
          border: `1px solid ${color.lightGrey}`,
          padding: `${scale.s3}rem`,
          marginBottom: `${scale.s3}rem`
        }}
        onChange={changeEvent => {
          form.setFieldValue(field.name, changeEvent.target.value);
          onChange(changeEvent.target.value);
        }}
        onKeyPress={onKeyPress}
        placeholder={placeholder ? placeholder : "Type something..."}
        type={type ? type : "text"}
      />
    </div>
  )
);

export default Input;

See it here in action.

虽然总的来说我不太确定你想做什么。您的表单工作正常,您可能不需要自定义 onChange 但也许您有一些特定的用例。

首先让我澄清一下这个答案只是为了帮助目的,我知道这个问题已经被接受但是如果上面的解决方案对任何人都不起作用,我确实对上面的答案做了一些修改我的版本

这里onChangeText会return数量字段的值

  <Formik
     initialValues={{ product_id: '', quantity: '', amount: '' }}
     onSubmit={(values, actions) => {
        this.submitLogin(values);
     }}

     //some other elements ....
    <Field placeholder='No. of Quantity' name='quantity' component={CustomInputComponent}
        onChangeText={value => {
           console.warn(value); // will get value of quantity
        }}
     />
  />

在你的class之外你可以定义你的组件

const CustomInputComponent = ({
   onChangeText,
   field, // { name, value, onChange, onBlur }
   form: { touched, errors, isValid, handleBlur, handleChange, values, setFieldValue }, // also values, setXXXX, handleXXXX, dirty, isValid, status, etc.
   ...props
}) => {
   return (
      <Input {...field} {...props} onBlur={handleBlur(field.name)}
        onChangeText={value => {
           setFieldValue(field.name, value);
           onChangeText(value); // calling custom onChangeText
        }}
     />
   )
}