当在 中通过数字键盘输入小数点(.)时,Formik 表单中的数值意外清空,根本原因在于 parseFloat() 在特定输入阶段接收到非法格式字符串(如空字符串或仅含 .),而非千分位逗号解析问题。
当在 `` 中通过数字键盘输入小数点(`.`)时,formik 表单中的数值意外清空,根本原因在于 `parsefloat()` 在特定输入阶段接收到非法格式字符串(如空字符串或仅含 `.`),而非千分位逗号解析问题。
该问题看似与区域化(locale)有关(例如误以为是逗号/句点分隔符混淆),实则源于 HTML 的输入生命周期特性与 parseFloat() 的严格解析规则之间的冲突。
? 问题本质分析
当用户在数字键盘上连续输入(如 12.)时:
- 浏览器会先将 12. 作为中间值写入 evt.target.value
- 此时 evt.target.value === "12."(末尾带英文句点)
- parseFloat("12.") 返回 12 ✅(合法)
- 但若用户只输入 .(尚未输入任何数字),此时 evt.target.value === "."
- parseFloat(".") 返回 NaN ❌
- Formik 调用 setFieldValue('formInvoice.amount', NaN) 后,若后续未做校验,NaN 可能被序列化为 "" 或触发重渲染异常,导致视觉上“值消失”
⚠️ 注意:这与千分位逗号(如 "1,234.56")完全无关——原答案误判了问题方向。parseFloat 本就不支持逗号,但本例中用户明确提到“用逗号无问题、用句点才消失”,说明实际触发场景是 value === "." 或 value === "" 等过渡态。
✅ 正确解决方案:安全解析 + 输入守卫
应避免在任意输入阶段直接 parseFloat(evt.target.value),而需增加合法性校验与容错处理:
? 进阶建议(提升用户体验)
-
使用 type="text" + 自定义验证:规避 在不同浏览器中对 . / - 的不一致处理(例如 Chrome 允许输入 12.,Safari 可能立即截断)。配合正则实时过滤:
// 允许:空、负号、数字、单个小数点、小数点后最多两位 const validPattern = /^-?\d*\.?\d{0,2}$/; if (!validPattern.test(rawValue)) return; - 配合 Formik 的 validate 或 yup schema:在提交时做强类型校验,而非依赖实时 onChange 解析。
- 显示格式与存储分离:UI 层显示 "12.50",但 amount 字段始终存为 number 类型;避免字符串与数字混用。
? 总结
- ❌ 错误归因:该问题与千分位逗号无关,parseFloat 对 "," 本就无效,但用户反馈“逗号可用”说明其输入内容不含逗号(如德语 locale 下数字键盘句点即小数点,逗号为千分位——但此处未启用 locale 格式化)。
- ✅ 正确路径:识别 onChange 中的中间非法状态(".", "-", ""),添加前置校验,再执行 parseFloat。
- ?️ 鲁棒性关键:永远假设 evt.target.value 可能为任意字符串,parseFloat 不是万能兜底,而是需配合防御性编程的工具函数。
遵循以上方案,即可彻底解决数字键盘输入小数点过程中值闪退或清空的问题,同时保障金额字段的数据完整性与用户体验一致性。










