You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

集成react-number-format后Formik的Yup验证失效问题求助

Fixing Formik + react-number-format + Yup Validation Issues

Here's the corrected implementation to get your formatted number input working with Formik and Yup validation properly:

Key Issues in Original Code

  • Initial value was an empty string, which Yup's number validation doesn't recognize as a valid numeric type
  • Attempting to use props.setFieldValue in the custom component (invalid, since Field doesn't pass this prop)
  • Inconsistent handling of value sync between the formatted input and Formik's state
  • Touched state not properly triggering validation feedback

Corrected Code

Step 1: Updated NumberField Component

This component uses Formik's useField hook to handle state updates and validation internally, eliminating the need to pass external state handlers:

import { Formik, Field, Form, useField } from 'formik';
import * as Yup from 'yup';
import { NumericFormat } from 'react-number-format';

const validationSchema = Yup.object({
  amount: Yup.number()
    .required("Amount is required")
    .positive("Amount must be positive")
    .max(20000000, "Maximum loan amount is 20,000,000"),
});

const NumberField = ({ name, ...props }) => {
  const [field, meta, helpers] = useField(name);

  const borderColor = !meta.touched
    ? "border-gray"
    : meta.error
    ? "border-red-500"
    : "border-gray";

  return (
    <div>
      <div className={`flex items-center border ${borderColor} rounded-md`}>
        <NumericFormat
          {...field}
          {...props}
          thousandSeparator
          decimalScale={2}
          fixedDecimalScale
          allowNegative={false}
          className="w-full py-2 px-2 border-none focus:outline-[#6DCCA0] outline-1 rounded-md"
          value={field.value ?? ""} // Show empty input when value is null
          onValueChange={(values) => {
            const { floatValue } = values;
            // Update Formik state: use null for empty input, otherwise the numeric value
            helpers.setValue(floatValue ?? null);
            // Mark field as touched on input change for immediate validation feedback
            helpers.setTouched(true);
          }}
          onBlur={field.onBlur} // Ensure touched state updates on focus loss
        />
      </div>
      {/* Display validation error if field is touched and has an error */}
      {meta.touched && meta.error && (
        <div className="text-red-500 text-sm mt-1">{meta.error}</div>
      )}
    </div>
  );
};

Step 2: Updated Formik Form

Simplified form implementation with correct initial values and no external state handlers needed:

<Formik
  initialValues={{
    amount: null, // Use null instead of empty string for proper numeric validation
  }}
  validationSchema={validationSchema}
  onSubmit={(values) => {
    console.log(values);
  }}
>
  {() => (
    <Form>
      <div className="mb-4 md:mb-6 md:pb-4 lg:pb-1">
        <label htmlFor="amount">Amount</label>
        <Field
          autoComplete="off"
          placeholder="USD"
          name="amount"
          component={NumberField}
        />
      </div>
      <button type="submit">Submit</button>
    </Form>
  )}
</Formik>

How This Works

  1. State Sync: Uses helpers.setValue from Formik's useField hook to update the Formik state with the raw numeric value from react-number-format's floatValue
  2. Validation Triggers: helpers.setTouched(true) ensures validation feedback shows immediately as the user types
  3. Input Handling: Converts null values to empty strings for the input display, maintaining consistency between Formik's numeric state and the formatted input
  4. Error Display: Self-contained error handling within the NumberField component keeps logic centralized

内容的提问来源于stack exchange,提问作者Chuks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 01:55:58