Formik表单重置后最后一个TextInput仍显示错误问题求助
这个问题我之前也碰到过,核心原因是Formik的默认重置行为没处理touched和errors状态——咱们一步步拆解解决:
问题根源
当你调用Formik的resetForm()时,它默认只会重置values对象,但不会清空touched和errors。因为提交前D输入框触发了onBlur,formikProps.touched.D已经被设为true;如果之前D还有验证错误,formikProps.errors.D也会保留。所以重置后,你的边框样式判断条件formikProps.touched[name] && formikProps.errors[name]依然成立,导致红色边框残留。
至于你尝试的ref.current.blur()没生效,是因为移除焦点本身不会改变Formik的touched状态——touched是在onBlur触发时被设置的,主动移除焦点不会把它改回false。
解决方案
下面提供两种靠谱的解决方式,你可以根据需求选择:
1. 重置表单时同时清空touched和errors
在Formik的提交回调里,调用resetForm时传入完整的重置状态,覆盖默认行为:
const handleSubmit = async (values, { resetForm }) => { // 执行你的提交逻辑,比如调用后端API try { await yourSubmitApi(values); // 重置values的同时,清空touched和errors对象 resetForm({ values: { A: '', B: '', C: '', D: '' }, // 替换成你的initialValues初始值 touched: {}, errors: {} }); // 可选:如果需要移除焦点,这里调用ref的blur inputDRef.current?.blur(); } catch (err) { // 处理提交失败的逻辑 } };
这样重置后,touched.D会变成false,边框样式的判断条件不再满足,红色边框自然消失。
2. 单独重置目标输入框的touched状态
如果你不想全量重置touched和errors,可以在提交成功后单独把D的touched设为false:
const handleSubmit = async (values, { resetForm, setFieldTouched }) => { await yourSubmitApi(values); resetForm(); // 先重置表单values setFieldTouched('D', false); // 把D的touched状态改为false inputDRef.current?.blur(); // 可选:移除输入框焦点 };
关于ref.blur()的补充说明
如果还是需要移除焦点,确保你的ref正确绑定到D输入框:
// 先定义ref const inputDRef = useRef(null); // 在D的TextInput组件上绑定ref <TextInput name="D" ref={inputDRef} // 其他props(placeholder、style等)... />
并且要在Formik状态更新后调用blur——上面两种方案里,放在resetForm之后调用就可以,因为resetForm会同步更新Formik的状态。
内容的提问来源于stack exchange,提问作者BraveEvidence

