在ReactHookForm中,应避免对已注册字段使用useState和value的混合控制,否则会导致watch()、getValues()及提交数据无法获取API填充值。正确做法是使用setValue或useController更新表单内部状态,确保字段参与验证、监听和提交。
在使用 React Hook Form 时,不少开发者容易犯一个错误:将受控输入(controlled input)与独立的 useState 状态混合使用。具体表现为,通过 useState 管理某个字段(例如 Street),再将其作为 value 传递给 。问题在于,React Hook Form 有其自身规则:所有已注册字段必须由 register 和内部状态统一管理,不能引入外部 state + value 的“半受控”模式。
一旦字段设置了 value={Street},React Hook Form 便会失去对该字段的控制权,导致其变为非受控或混合受控状态。后果是 watch()、getValues() 以及最终提交的数据中,API 写入的值全部无法读取。
长期稳定更新的攒劲资源: >>>点此立即查看<<<

正确做法非常简单:去掉 useState 对字段的多余管理,直接使用 setValue 更新表单内部状态。查看以下完整实现,即可清晰理解:
import { useForm } from 'react-hook-form';function OrderForm() { const { register, handleSubmit, watch, setValue, getValues } = useForm(); const cep = watch('CEP'); // 验证 CEP 格式 const isCepValid = /^[0-9]{5}-[0-9]{3}$/.test(cep); // 监听 CEP 变化,自动调用 API 填充 Street useEffect(() => { const fetchCepData = async () => { if (!isCepValid) { setValue('Street', ''); return; } try { const response = await fetch(`https://viacep.com.br/ws/${cep}/json/`); const data = await response.json(); if (!data.erro) { setValue('Street', data.logradouro || ''); // 关键:用 setValue 同步到表单状态 } else { setValue('Street', ''); } } catch (error) { console.error('CEP lookup failed:', error); setValue('Street', ''); } }; // 防抖处理,避免频繁请求 const timer = setTimeout(fetchCepData, 300); return () => clearTimeout(timer); }, [cep, isCepValid, setValue]); const onSubmit = (data) => { console.log('Submitted form data:', data); // Street 将包含 API 值 addOrderInfos(data); na vigate('/success'); }; return ( );}
useState 和 value 属性,这会导致字段不参与 React Hook Form 的内部管理,引发数据不同步问题。setValue('fieldName', newValue) 主动写入表单状态,确保字段参与验证、监听和提交流程。setValue 支持第三个参数,例如 { shouldValidate: true, shouldDirty: true },可用于触发校验或标记字段为“已修改”,实用性较强。useEffect 的依赖项:仅监听 cep 即可,避免直接使用 watch('CEP') 的返回结果,否则容易引发无限循环。setValue,或直接使用 reset({ ... }) 一次性完成填充。经过上述调整后,watch('Street')、getValues() 以及最终提交的数据均可准确反映 API 填充的内容,彻底解决“字段不被注册”的常见问题。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述