集成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.setFieldValuein the custom component (invalid, sinceFielddoesn'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
- State Sync: Uses
helpers.setValuefrom Formik'suseFieldhook to update the Formik state with the raw numeric value fromreact-number-format'sfloatValue - Validation Triggers:
helpers.setTouched(true)ensures validation feedback shows immediately as the user types - Input Handling: Converts null values to empty strings for the input display, maintaining consistency between Formik's numeric state and the formatted input
- Error Display: Self-contained error handling within the NumberField component keeps logic centralized
内容的提问来源于stack exchange,提问作者Chuks
相关产品推荐
相关产品推荐

