react-hook-form结合react-number-format使用时isDirty状态异常问题
react-number-format 配合 react-hook-form Controller 组件 isDirty 不更新问题解决方案
问题根因
- react-hook-form 的
isDirty和dirtyFields基于当前值与默认值的严格相等(===) 逻辑判断,只有两者完全一致时才会判定为未修改。 - react-number-format 相关字段返回值和默认值类型不匹配:
- 若取
floatValue字段,清空输入时返回值为undefined,undefined === ''结果为false - 若错误使用带格式的
formattedValue作为提交值,和纯文本默认值的判定也会不匹配 - 部分特殊场景下清空输入会返回
null,同样和空字符串严格相等判断不成立
因此即使视觉上输入框为空,值和默认值判定为不一致,isDirty始终为true。
- 若取
修复方案
方案1:统一空值输出类型(最推荐)
在onValueChange回调中做一层值转换,保证清空输入时输出和defaultValue完全一致的类型:
// 示例:defaultValue设置为空字符串的场景 <Controller name="currency" control={control} defaultValue="" render={({ field }) => ( <NumericFormat thousandSeparator prefix="¥" value={field.value} onValueChange={(values) => { // 空输入时统一转成空字符串,和defaultValue完全匹配 const submitValue = values.value || ''; field.onChange(submitValue); }} onBlur={field.onBlur} /> )} />
如果业务需要存储数字类型,把默认值改成undefined即可:
// 示例:值为数字类型的场景 <Controller name="currency" control={control} defaultValue={undefined} render={({ field }) => ( <NumericFormat thousandSeparator prefix="¥" value={field.value} onValueChange={(values) => { // 空输入时返回undefined,和defaultValue完全匹配 field.onChange(values.floatValue ?? undefined); }} onBlur={field.onBlur} /> )} />
方案2:自定义脏值判断逻辑
如果不想修改值的输出逻辑,可以在使用isDirty时自定义比较逻辑,兼容空类值的判定:
const { formState, getValues } = useForm({ defaultValues: { currency: '' } }); // 自定义脏值判定,兼容空值场景 const isFormDirty = () => { const currentVal = getValues('currency'); // 空字符串、undefined、null都判定为和默认空字符串一致 if (!currentVal) return false; return formState.isDirty; }
内容的提问来源于stack exchange,提问作者RanST
相关产品推荐
相关产品推荐

