Formik表单onChange事件中如何获取input.value并实现实时字符校验替换
Formik 表单实时替换输入非法字符实现方案
核心思路是重写输入框的onChange事件,先对输入值做格式化处理,再手动同步到Formik的状态中,不会破坏Formik原有校验、提交逻辑。
第一步:修改通用FormInput组件
新增可选的formatFunc入参,用于传入自定义的格式化函数,适配不同字段的处理需求,修改后代码如下:
import React from 'react'; import { ErrorMessage, useField, useFormikContext } from 'formik'; import './formInput.scss'; const FormInput = ({label='', placeholder=null, classNames='', formatFunc, ...props}) => { const [field, meta] = useField(props); const { setFieldValue, setFieldTouched } = useFormikContext(); const handleChange = async (e) => { let inputValue = e.target.value; // 若传入格式化函数则预处理输入值 if (typeof formatFunc === 'function') { inputValue = formatFunc(inputValue); } // 同步处理后的值到Formik状态 await setFieldValue(field.name, inputValue); // 标记字段已触碰,实时触发校验提示 setFieldTouched(field.name, true, false); }; return ( <div className="form__input-wrapper"> <label htmlFor={field.name}>{label}</label> <input className={`${classNames}`} {...props} name={field.name} value={field.value || ''} onChange={handleChange} onBlur={field.onBlur} /> {meta.touched && meta.error ? (<div>{meta.error}</div>) : null} </div> ) } export default FormInput;
第二步:给需要格式化的字段传入处理函数
以手机号字段只允许输入数字为例,注意你用到的替换正则要加g全局标识符,否则只会替换第一个非数字字符:
<FormInput label="手机号" name="phone" type="phone" formatFunc={(str) => str.replace(/\D/g, '')} />
其他字段如果有不同的格式化需求,传入对应处理函数即可,无需修改组件本身。
注意事项
- Formik的
initialValues要确保每个字段都有初始值(比如空字符串),否则输入时可能出现非受控组件报错 - 原有Yup校验逻辑无需修改,预处理后的值会正常走你定义的校验规则
- 如果不需要实时触发校验提示,可以删除
setFieldTouched那行代码,等用户失焦再显示错误
内容的提问来源于stack exchange,提问作者Wells
相关产品推荐
相关产品推荐

